术语,嵌套文档和must_not查询在ElasticSearch中不兼容?

时间:2014-03-07 15:28:33

标签: elasticsearch nested term

我在嵌套文档上组合术语,must_not查询时遇到问题。

感觉示例可以在这里找到:http://sense.qbox.io/gist/be436a1ffa01e4630a964f48b2d5b3a1ef5fa176

这是我的映射:

{
    "mappings": {
        "docs" : {
            "properties": {
                "tags" : {
                    "type": "nested",
                    "properties" : {
                        "type": {
                           "type": "string",
                           "index": "not_analyzed"
                        }
                    }
                },
                "label" : {
                    "type": "string"
                }
            }
        }
    }
}

在此索引中包含两个文档:

{
    "tags" : [
        {"type" : "POST"},
        {"type" : "DELETE"}
    ],
    "label" : "item 1"
},
{
    "tags" : [
        {"type" : "POST"}
    ],
    "label" : "item 2"
}

当我像这样查询这个索引时:

{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "bool": {
          "must": {
            "term": {
              "tags.type": "DELETE"
            }
          }
        }
      }
    }
  }
}

我有一次点击(这是正确的)

当我想要获取不包含标签“DELETE”的文档时,使用此查询:

{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "bool": {
          "must_not": {
            "term": {
              "tags.type": "delete"
            }
          }
        }
      }
    }
  }
}

我有2次点击(不正确)。 这个问题似乎非常接近这个问题(Elasticsearch array must and must_not),但它不是......

你能给我一些解决这个问题的线索吗?

谢谢

2 个答案:

答案 0 :(得分:15)

您的原始查询将搜索每个单独的嵌套对象并消除不匹配的对象,但如果还有一些嵌套对象,则它们会与您的查询匹配,从而获得结果。这是因为嵌套对象 被索引为隐藏的单独文档

原始代码:

{
  "query": {
    "nested": {
      "path": "tags",
      "query": {
        "bool": {
          "must_not": {
            "term": {
              "tags.type": "delete"
            }
          }
        }
      }
    }
  }
}

解决方案非常简单,你应该将bool查询带到嵌套文档之外。现在丢弃所有具有“ DELETE ”类型的嵌套对象的文档。正是你想要的!

解决方案:

{
  "query": {
    "bool": {
      "must_not": {
        "nested": {
          "path": "tags",
          "query": {
            "term": {
              "tags.type": "DELETE"
            }
          }
        }
      }
    }
  }
}

注意:您的字符串“未分析”并且您搜索“删除”而不是“删除”。如果您想搜索不区分大小写,请分析字符串

答案 1 :(得分:0)

这可以解决您的问题:http://sense.qbox.io/gist/f4694f542bc76c29624b5b5c9b3ecdee36f7e3ea

两件最重要的事情:

  1. include_in_root on“tags.type”。这将告诉ES将标记类型索引为"doc.tags.types" : ['DELETE', 'POSTS'],因此您可以在根文档上访问“flattened”这些值的数组。这意味着您不再需要嵌套查询(请参阅#2)

  2. 删除嵌套查询。

  3. {
        "mappings": {
            "docs" : {
                "properties": {
                    "tags" : {
                        "type": "nested",
                        "properties" : {
                            "type": {
                               "type": "string",
                               "index": "not_analyzed"
                            }
                        },
                        "include_in_root": true
                    },
                    "label" : {
                        "type": "string"
                    }
                }
            }
        }
    }
    

    {
       "query": {
          "bool": {
             "must_not": {
                "term": {
                   "tags.type": "DELETE"
                }
             }
          }
       }
    }