【问题标题】:How can I skip indexing a specific property, but still retrieve its contents when querying in Elasticsearch and NEST?如何跳过索引特定属性,但在 Elasticsearch 和 NEST 中查询时仍检索其内容?
【发布时间】:2019-02-27 00:10:05
【问题描述】:

给定这个索引模型类:

public class ProductIndexModel
{
    public Guid Id { get; set; }
    public DateTime Created { get; set; }
    public string Name { get; set; }
    public JObject DynamicContent { get; set; }
}

我正在努力做到以下几点:

  • 将整个对象存储在 Elasticsearch 中
  • 索引所有属性,除了DynamicContent属性
  • 查询时,检索整个对象(包括DynamicContent prop)

我不索引 DynamicContent 属性的原因是,它是一个 json-blob,偶尔会有不同类型的属性路径之间发生冲突(例如对象与字符串、int 与字符串等) )。例如,尝试使用 2 个对象来索引路径 /dynamiccontent.id,其中 value 分别为 int 和 string 类型可能会给我:

错误:类型:mapper_parsing_exception 原因:“解析失败 [dynamiccontent.id]" CausedBy:类型:json_parse_exception 原因: “当前令牌 (START_OBJECT) 不是数字,不能使用数值 访问器

我是这样创建索引的:

var createIndexResponse = await _elasticClient.CreateIndexAsync(indexName, c => c
    .InitializeUsing(settingsState)
    .Mappings(ms => ms
        .Map<ProductIndexModel>(m => m
            .AutoMap()
        )
    )
);

settingsState 的类型为 Nest.IndexState,带有一些标记器等等,这与问题无关。

ISearchRequest SearchRequest(SearchDescriptor<ProductIndexModel> x) => x
    .Index(indexName)
    .Query(q => q.Bool(bq => bq.Filter(filters)))
    .From(filter.Offset)
    .Size(filter.PageSize)
;

var searchResponse = await _elasticClient.SearchAsync<ProductIndexModel>(SearchRequest);

filters 是一个动态构造的通用过滤器列表,用于减少结果。

所以我想保持DynamicContent 未编入索引,但在查询时仍然能够获取其(原始)内容。

我试图用 Nest.IgnoreAttribute 注释 DynamicContent 完全忽略它,因此在检索时导致空值。关于如何使用 NEST “存储”值而不是索引它的任何建议?

【问题讨论】:

    标签: elasticsearch nest


    【解决方案1】:

    由于DynamicContent 是Json.NET JObject 类型,如果您使用的是NEST 6.x,则需要hook up the JsonNetSerializer 才能正确索引JObject 的实例。

    一旦这个序列化器被连接,你可以用[Object(Enabled = false)]来给模型赋值,它设置enabled=false for the field,这意味着该属性被持久化在_source中,但不被解析或索引。

    特别是JObject,NEST 的自动映射(映射时需要考虑该属性)将为JObject 生成一个大的"properties" 对象,这是完全不必要的,因为该字段不会被解析或索引。在这种特殊情况下,流畅的映射将是比属性映射更好的选择。这是一个例子:

    private static void Main()
    {
        var defaultIndex = "default_index";
        var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
    
        var settings = new ConnectionSettings(pool, JsonNetSerializer.Default)
            .DefaultIndex(defaultIndex)
            .DefaultTypeName("_doc");
    
        var client = new ElasticClient(settings);
    
        if (client.IndexExists(defaultIndex).Exists)
            client.DeleteIndex(defaultIndex);
    
        var createIndexResponse = client.CreateIndex(defaultIndex, c => c
            .Mappings(m => m
                .Map<ProductIndexModel>(mm => mm
                    .AutoMap() // <-- automap
                    .Properties(p => p
                        .Object<JObject>(o => o
                            .Name(n => n.DynamicContent) <-- override the automap inferred mapping for DynamicContent
                            .Enabled(false)
                        )
                    )
                )
            )
        );
    
        var indexResponse = client.Index(new ProductIndexModel
        {
            Id = Guid.NewGuid(),
            Created = DateTime.UtcNow,
            Name = "foo",
            DynamicContent = new JObject 
            {
                { "prop1", "value1" },
                { "prop2", new JArray(1, 2, 3, 4) }
            }
        }, i => i.Refresh(Refresh.WaitFor));
    
        var searchResponse = client.Search<ProductIndexModel>(s => s
            .MatchAll()
        );
    }
    
    public class ProductIndexModel
    {
        public Guid Id { get; set; }
        public DateTime Created { get; set; }
        public string Name { get; set; }
        [Object(Enabled = false)]
        public JObject DynamicContent { get; set; }
    }
    

    【讨论】:

    • 嗨,Russ,非常感谢您抽出宝贵时间写出如此出色而详细的答案!你确实帮我解决了这个问题 - Enabled 标志对我来说有点神秘,然后我也在尝试中给我做了一些瑞士奶酪问题,但你的回答让我回到了正轨。最后一件事:当使用 REST Api elastic.co/guide/en/elasticsearch/reference/current/… 而不是流畅的方式时,是否有可能在使用 Nest 创建索引时使用 JSON 中定义的映射覆盖 Automap()?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多