小编典典

匹配完整的复杂嵌套集合项,而不是通过Elastic Search匹配单独的成员

elasticsearch

我有一个索引,其中包含我要命中的项目的嵌套集合。集合项包含多个必须全部与某个查询匹配的属性,而不仅仅是其中的任何一个。这是模型:

public class IndexEntry1
{
    public IEnumerable<NestedType1> NestedProperty1 { get; set; }
}

public class NestedType1
{
    public string Member1 { get; set; }
    public string Member2 { get; set; }
}

因此,我只想点击集合中具有Member1Member2值特定组合的文档IndexEntry1.NestedProperty1

我认为必须将集合映射为嵌套。

这是映射:

index: {
    properties: {
        nestedProperty1: {
            type: "nested",
            properties: {
                member1: {
                    type: "string",
                    index_analyzer: "my_index_analyzer_1",
                    search_analyzer: "my_search_analyzer_1"
                },
                member2: {
                    type: "string",
                    analyzer: "keyword"
                }
            }
        }
    },
    analysis: {
        tokenizer: {
            my_ngram: {
                type: "nGram",
                min_gram: "1",
                max_gram: "15"
            }
        },
        analyzer: {
            my_index_analyzer_1: {
                type: "custom",
                tokenizer: "my_ngram",
                filters: ["lowercase"]
            },
            my_search_analyzer_1: {
                type: "custom",
                tokenizer: "whitespace",
                filters: ["lowercase"]
            }
        }
    }
}

并使用如下查询:

client.Search<IndexEntry1>(d => d
    .Query(query => query
        .Nested(n => n
            .Path(p => p.NestedProperty1)
                .Query(q => q
                    .Bool(b => b
                        .Must(
                            m => m.Term("member1", "value1"),
                            m => m.QueryString(s => s.OnField("member2")
                                .Query("value2"))))))));

但是,我仍然会遇到具有该value1值或该value2值的任何文档的命中,而我希望仅对具有相同值的两个值在同一NestedProperty1收集项目上的文档进行命中。


阅读 249

收藏
2020-06-22

共1个答案

小编典典

您是正确的,它只应查找嵌套文档具有value1和value2的文档。

您可以通过合理运行以下命令(chrome插件)来观察这是Elasticsearch的行为:

PUT http://localhost:9200/nested_example
{
    "mappings": {
        "indexentry" : {
            "properties": {
                "nestedCollection": {
                    "type": "nested",
                    "properties": {
                        "prop1" : { "type": "string", "index": "not_analyzed" },
                        "prop2" : { "type": "string", "index": "not_analyzed" }
                    }
                }
            } 
        }
    }
}
POST http://localhost:9200/nested_example/indexentry/1
{
    "nestedCollection": [
        { "prop1" : "A", "prop2" : "A" },
        { "prop1" : "B", "prop2" : "B" }
    ]
}
POST http://localhost:9200/nested_example/indexentry/2
{
    "nestedCollection": [
        { "prop1" : "C", "prop2" : "C" },
        { "prop1" : "D", "prop2" : "D" }
    ]
}

POST http://localhost:9200/nested_example/indexentry/_search
{
    "query": {
        "nested": {
           "path": "nestedCollection",
           "query": {
                "bool": {
                    "must": [
                       {
                           "term": {
                              "nestedCollection.prop1": {
                                 "value": "A"
                              }
                           }
                       },
                       {
                           "term": {
                              "nestedCollection.prop2": {
                                 "value": "A"
                              }
                           }
                       }

                    ]
                }
           }
        }
    }
}

先前的查询将仅找到文档,1但是一旦您更改术语查询nestedColleciton.prop2以查找B而不是A您,将不再获得预期的任何响应。

如果我更新该示例以使其更符合您的映射和查询,则无法重现您的见证行为:

PUT http://localhost:9200/nested_example
{
   "settings": {
      "analysis": {
         "tokenizer": {
            "my_ngram": {
               "type": "nGram",
               "min_gram": "1",
               "max_gram": "15"
            }
         },
         "analyzer": {
            "my_index_analyzer_1": {
               "type": "custom",
               "tokenizer": "my_ngram",
               "filters": [
                  "lowercase"
               ]
            },
            "my_search_analyzer_1": {
               "type": "custom",
               "tokenizer": "whitespace",
               "filters": [
                  "lowercase"
               ]
            }
         }
      }
   },
   "mappings": {
      "indexentry": {
         "properties": {
            "nestedCollection": {
               "type": "nested",
               "properties": {
                  "prop1": {
                     "type": "string",
                     "index_analyzer": "my_index_analyzer_1",
                     "search_analyzer": "my_search_analyzer_1"
                  },
                  "prop2": {
                     "type": "string",
                     "analyzer": "keyword"
                  }
               }
            }
         }
      }
   }
}
POST http://localhost:9200/nested_example/indexentry/1
{
    "nestedCollection": [
        { "prop1" : "value1", "prop2" : "value1" },
        { "prop1" : "value2", "prop2" : "value2" }
    ]
}
POST http://localhost:9200/nested_example/indexentry/2
{
    "nestedCollection": [
        { "prop1" : "value3", "prop2" : "value3" },
        { "prop1" : "value4", "prop2" : "value4" }
    ]
}

POST http://localhost:9200/nested_example/indexentry/_search
{
    "query": {
        "nested": {
           "path": "nestedCollection",
           "query": {
                "bool": {
                    "must": [
                       {
                           "term": {
                              "prop1": {
                                 "value": "value1"
                              }
                           }
                       },
                       {
                           "query_string": {
                               "fields": [
                                  "prop2"
                               ],
                               "query": "value1"

                           }
                       }

                    ]
                }
           }
        }
    }
}

您可以更新前面的示例以更好地重现您的情况吗?

在NEST中,您可以将查询重写为:

client.Search<IndexEntry1>(d => d
    .Query(query => query
        .Nested(n => n
            .Path(p => p.NestedProperty1)
            .Query(q => 
                q.Term(p => p.NestedProperty1.First().Member1, "value1")
                && q.QueryString(s => s
                    .OnField(p => p.NestedPropery1.First().Member2)
                    .Query("value2")
                )
            )
        )
    );

类型强,嵌套少。

2020-06-22