【问题标题】:Term, nested documents and must_not query incompatible in ElasticSearch?ElasticSearch 中的术语、嵌套文档和 must_not 查询不兼容?
【发布时间】:2014-03-07 15:28:32
【问题描述】:

我无法在嵌套文档中组合 term、must_not 查询。

可以在此处找到 Sense 示例: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),但它不是......

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

谢谢

【问题讨论】:

    标签: elasticsearch nested


    【解决方案1】:

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

    原码:

    {
      "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"
                }
              }
            }
          }
        }
      }
    }
    

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

    【讨论】:

    • 如果我这样做,没有标签字段的数据不会包含在结果中
    • 你确定吗?您使用哪个 Elasticsearch 版本?
    • 弹性搜索 2.2.1。重新检查后,很多查询在我的笔记本电脑上工作正常,但在服务器上。 Elasticsearch 版本可能会起作用。
    • 我认为您的意思是 not 在服务器中。您在那里使用哪个 ES 版本? ALL 查询是否在笔记本电脑上工作?如果他们这样做了,我认为我的解决方案仍然有效。事实上,我每天都在生产中使用这个解决方案......
    • 它在服务器上不起作用,服务器使用2.2.1版本,就像我在之前的评论中所说的那样。我还没有在自己的笔记本电脑上尝试过
    【解决方案2】:

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

    两件最重要的事情:

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

    2. 删除嵌套查询。

     

    {
        "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"
                }
             }
          }
       }
    }
    

    【讨论】:

    • 谢谢,它有效。你能解释一下你为什么这样做吗?
    • 仅仅是因为没有“include_in_root”是不可能的。您现在可以将所有“tags.type”视为一个数组,而不是拥有一个复杂的嵌套过滤器/查询系统。这样,您可以说“给我所有标签类型数组中没有'DELETE'的文档”。有时用语言表达这些东西并不容易,但希望这是有道理的!
    • 它对我不起作用。这既奇怪又可悲。是不是因为我使用了termsinteger
    • 你也可以"include_in_parent": true
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多