带过滤器的 ElasticSearch 嵌套查询

ElasticSearch nested query with filter

好的,对于你们这些超级棒的 ElasticSearch 专家来说,这可能不会太难。我有这个嵌套查询,我希望在非嵌套字段(状态)上过滤嵌套查询。我不知道把过滤器放在哪里。我尝试将其放入查询(如下)中,但这并没有给我正确的结果。你能帮帮我吗?

{
  "aggs": {
    "status": {
      "terms": {
        "field": "status",
        "size": 0
      }
    }
  },
  "filter": {
    "nested": {
      "path": "participants",
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "user_id": 1
              }
            },
            {
              "term": {
                "archived": false
              }
            },
            {
              "term": {
                "has_unread": true
              }
            }
          ]
        }
      }
    }
  },
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must_not": [
            {
              "term": {
                "status": 8
              }
            }
          ]
        }
      }
    }
  }
}

这里有几个动人的片段:

  1. The top-level filter that you are using is a "post filter",目的是在 聚合处理后 删除内容。它以这种方式存在很烦人,但它在 0.90 天就被弃用了,它将在 Elasticsearch 5.0 中完全删除。

    将它放在过滤查询中很可能会获得更好的性能,更不用说这听起来像是您的目标。

    • 它的替代品更恰当地命名为 post_filter
  2. 您的 nested filter 的条款 使用字段的完整路径,您应该这样做。

    {
      "term": {
        "user_id": 1
      }
    }
    

    应该是:

    {
      "term": {
        "participants.user_id": 1
      }
    }
    

    其余嵌套对象也是如此。

  3. 假设您不希望 status 成为 8,那么您就完美地做到了。

  4. 在聚合中使用 0size 意味着您将获得 所有内容 。这适用于较小的数据集,但在较大的数据集上会很痛苦。

将它们放在一起(顺序无关紧要,但将聚合 放在查询部分 之后通常是个好主意,因为这就是它的执行方式):

{
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must" : {
            "nested" : {
              "path" : "participants",
              "filter": {
                "bool": {
                  "must": [
                    {
                      "term": {
                        "participants.user_id": 1
                      }
                    },
                    {
                      "term": {
                        "participants.archived": false
                      }
                    },
                    {
                      "term": {
                        "participants.has_unread": true
                      }
                    }
                  ]
                }
              }
            }
          },
          "must_not": {
            "term": {
              "status": 8
            }
          }
        }
      }
    }
  },
  "aggs": {
    "status": {
      "terms": {
        "field": "status",
        "size": 0
      }
    }
  }
}

注意:我将 "must_not" 部分从数组更改为单个对象。 always 使用数组语法没有任何问题,但我只是没有证明这两种格式都有效。自然地,如果你使用了不止一项,那么你必须使用数组语法。