【问题标题】:How can I execute ElasticSearch query on multiple indices with nested mapping如何使用嵌套映射对多个索引执行 ElasticSearch 查询
【发布时间】:2019-09-20 21:01:18
【问题描述】:

我有两个具有以下配置的索引和映射

var settings = new ConnectionSettings(new Uri("http://localhost:9200/"));
settings
      .DefaultMappingFor<ManagementIndex>(m => m
          .IndexName("management")
      )
      .DefaultMappingFor<PropertyIndex>(m => m
          .IndexName("apartmentproperty")
      );
var client = new ElasticClient(settings);


1) 属性映射

client.Indices.Create("property", i => i
                .Settings(s => s
                    .NumberOfShards(2)
                    .NumberOfReplicas(0)
                )
                .Map<PropertyIndex>(map => map
                    .AutoMap()
                    .Properties(p => p
                        .Nested<PropertyData>(n => n
                            .Name(c => c.property)
                            .AutoMap()
                            .Properties(pp => pp
                                .Text(c => c
                                    .Name(np => np.city)
                                    .Analyzer("standard")
                                )
                                .Text(c => c
                                    .Name(np => np.market)
                                    .Fields(ff => ff
                                        .Text(tt => tt
                                            .Name(np => np.market)
                                            .Analyzer("standard")
                                        )
                                        .Keyword(k => k
                                            .Name("keyword")
                                            .IgnoreAbove(256)
                                        )
                                    )
                                ).Text(c => c
                                    .Name(np => np.name)
                                    .Analyzer("standard")
                                )

                            )
                        )
                    )
                )
            );

2) 所有者

if (client.Indices.Exists("owner").Exists)
                client.Indices.Delete("owner");

            client.Indices.Create("owner", i => i
                .Settings(s => s
                    .NumberOfShards(2)
                    .NumberOfReplicas(0)
                )
                .Map<OwnerIndex>(map => map
                    .AutoMap()
                    .Properties(p => p
                        .Nested<OwnerProp>(n => n
                            .Name(c => c.owner)
                            .AutoMap()
                            .Properties(pp => pp
                                .Text(c => c
                                    .Name(np => np.market)
                                    .Fields(ff => ff
                                        .Text(tt => tt
                                            .Name(np => np.market)
                                            .Analyzer("standard")
                                        )
                                        .Keyword(k => k
                                            .Name("keyword")
                                            .IgnoreAbove(256)
                                        )
                                    )
                                ).Text(c => c
                                    .Name(np => np.name)
                                    .Analyzer("standard")
                                )
                            )
                        )
                    )
                )
            );

具有以下 POCO 定义

    public class PropertyData
    {
        public string name { get; set; }
        public string city { get; set; }
        public string market { get; set; }
    }

    public class PropertyIndex
    {
        public PropertyData property { get; set; }
    }

    public class OwnerProp
    {
        public string name { get; set; }
        public string market { get; set; }
    }

    public class OwnerIndex
    {
        public OwnerProp owner { get; set; }
    }


尝试像这样通过两个索引进行搜索

 public async Task<object> SearchPropertiesAsync(string searchQuery, List<string> description, int limit = 25, int skip = 1)
        {
            var propertyfilters = new List<Func<QueryContainerDescriptor<object>, QueryContainer>>();
            var ownerFilters = new List<Func<QueryContainerDescriptor<object>, QueryContainer>>();
            if (description.Any())
            {
                propertyfilters.Add(fq => fq.Terms(t => t.Field("property.market.keyword").Terms(description)));
                ownerFilters.Add(fq => fq.Terms(t => t.Field("owner.market.keyword").Terms(description)));
            }

            var searchResponse = await _elasticClient.SearchAsync<object>(s => s
                .Index(Indices.Index(typeof(PropertyIndex)).And(typeof(OwnerIndex)))

                .Query(q => (q
                    .Nested(n => n

                    .Path(Infer.Field<PropertyIndex>(ff => ff.property))

                    .Query(nq => nq

                    .MultiMatch(m => m

                        .Fields(f => f
                            .Field(Infer.Field<PropertyIndex>(ff => ff.property.city))
                            .Field(Infer.Field<PropertyIndex>(ff => ff.property.market))
                            .Field(Infer.Field<PropertyIndex>(ff => ff.property.name))
                        )
                        .Operator(Operator.Or)
                        .Query(searchQuery)
                        .Fuzziness(Fuzziness.Auto)
                    )  && +q.Bool(bq => bq.Filter(propertyfilters))
                        ))
                    ) || (q
                    .Nested(n => n
                    .Path(Infer.Field<OwnerIndex>(ff => ff.mgmt))
                    .Query(nq => nq

                    .MultiMatch(m => m
                        .Fields(f => f
                            .Field(Infer.Field<OwnerIndex>(ff => ff.owner.market))
                            .Field(Infer.Field<OwnerIndex>(ff => ff.owner.name))
                        )
                        .Operator(Operator.Or)
                        .Query(searchQuery)
                        .Fuzziness(Fuzziness.Auto)
                    ) 
                    && +q.Bool(bq => bq.Filter(ownerFilters))
                    ))
                    )
                ).From((skip - 1) * limit)
                    .Size(limit)
            );

            return searchResponse.Documents;
        }

调用SearchPropertiesAsync 方法会返回此错误消息(为简洁起见被截断)

         ....
          "index": "owner",
          "caused_by": {
            "type": "illegal_state_exception",
            "reason": "[nested] failed to find nested object under path [property]"
          }

         ....
          "index": "property",
          "caused_by": {
            "type": "illegal_state_exception",
            "reason": "[nested] failed to find nested object under path [owner]"
          }

请注意,它似乎试图在 property 索引上执行 owner. 的嵌套搜索,并在不存在的 owner 索引上执行 property. 的嵌套搜索。

我觉得这应该是一个非常微不足道的问题,但我现在使用 ElasticSearch 才 4 天,而且对它还是很陌生。

是我做错了什么还是我遗漏了什么。已经搜索了整个互联网,甚至得出了我目前的解决方案。

请注意,当您一次只执行一个索引时,代码可以正常工作,但尝试在多个索引上执行是我的问题所在。任何帮助将不胜感激。

我正在使用 ElasticSearch 7.3.2 和 Nest Client 7.3.0。

我不介意降级到可用的较低版本。

【问题讨论】:

    标签: elasticsearch asp.net-core nest elasticsearch.net


    【解决方案1】:

    显然,根据文档

    ignore_unmapped (可选,布尔值)指示是否忽略未映射的路径并且不返回任何文档而不是错误。默认为 false。

    如果为 false,如果路径是未映射的字段,则 Elasticsearch 会返回错误。

    您可以使用该参数查询多个可能不包含字段路径的索引。

    因此,在每个嵌套查询的查询正文上链接 .IgnoreUnmapped(true) 解决了这个问题。 以防万一其他人遇到同样的问题

    【讨论】:

      猜你喜欢
      • 2017-06-16
      • 2018-08-20
      • 2017-09-19
      • 1970-01-01
      • 2018-09-18
      • 1970-01-01
      • 2018-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多