首页 > 解决方案 > 按嵌套对象的长度过滤查询。IE。min_child

问题描述

我正在尝试按找到的嵌套对象的数量过滤我的查询。Elastic Search 文档提到使用脚本是一项昂贵的任务,因此我已经着手使用分数来完成,尽管我似乎也无法让脚本正常工作。

这是我的映射:

"mappings": {
  "properties": {
    "dates" : {
      "type" : "nested",
      "properties" : {
        "rooms" : {
          "type" : "integer"
        },
        "timestamp" : {
          "type" : "long"
        }
      }
    },
    "doc_id" : {
      "type" : "text"
    },
    "distance" : {
      "type" : "integer"
    }
    ...
  }
}

以下是一些示例数据:

PUT /test/_doc/1
{
  "doc_id": "1",
  "distance": 1,
  "dates": [
    {
      "rooms": 1,
      "timestamp": 1
    },
    {
      "rooms": 1,
      "timestamp": 2
    },
    ...
  ]
}

我正在按 parentsdistance字段等进行过滤,并按dates他们的timestamps, 和rooms. 我需要将所有结果过滤为找到的确切数量的嵌套日期。

我试图从这里借钱。

这是我的搜索查询:

GET /test/_search
{
  "query" : {
    "function_score": {
      "min_score": 20,
      "boost": 1,
      "functions": [
        {
          "script_score": {
            "script": {
                "source": "if (_score > 20) { return - 1; } return _score;"
            }
          }
        }
      ],
      "query": {
        "bool" : {
          "filter": [
            { "range": { "distance": { "lt": 5 }}},
            {
              "nested": {
                "score_mode": "sum",
                "boost": 10,
                "path": "dates",
                "query": {
                  "bool": {
                    "filter": [
                      { "range": { "dates.rooms": { "gte": 1 } } },
                      { "range": { "dates.timestamp": { "lte": 2 }}},
                      { "range": { "dates.timestamp": { "gte": 1 }}}
                    ]
                  }
                }
              }
            }
          ]
        }
      }
    }
  }
}

这将返回所有匹配的结果,但它们的分数均为 0.0,并且没有被找到的嵌套对象的数量过滤。

如果这是正确的解决方案,我怎样才能让它工作?如果没有,我怎样才能在这个搜索中获得一个脚本来完成它?

谢谢!

标签: elasticsearch

解决方案


在开始之前,请记住评分功能在 Elastic 6 和 7 之间发生了变化。您可以在此 gist上找到更新的代码示例。

您的问题没有概述您的搜索细节。看代码,好像要检索所有距离小于5的文档,匹配的房间数正好是2。如果正确的话,你提交的代码并没有实现这个。

原因:您的功能分数包含您的主要条件和匹配房间数量的条件(将两者混合起来非常棘手,尽管并非不可能)。为了使事情更简单,将它们隔离起来,使功能分数仅适用于房间数量。

假设您使用的是 elastic 7+,这可能会起作用:

{
  "_source": {
    "includes": ["*"],
    "excludes": ["dates"]
  },
  "query": {
    "bool": {
      "must": [
        {"range": {"distance": {"lt": 5}}},
        {
          "function_score": {
            "min_score": 20,
            "boost": 1,
            "score_mode": "multiply",
            "boost_mode": "replace",
            "functions": [
              {
                "script_score": {
                  "script": {
                    "source": "if (_score > 20) { return 0; } return _score;"
                  }
                }
              }
            ],
            "query": {
              "nested": {
                "path": "date",
                "boost": 10,
                "score_mode": "sum",
                "query": {
                  "constant_score": {
                    "boost": 1,
                    "filter": {
                      "bool": {
                        "should": [
                          {
                            "bool": {
                              "must": [
                                {"term": {"dates.timestamp": 1}},
                                {"range": {"dates.rooms": {"lt": 5}}}
                              ],
                              "should": [
                                {"term": {"dates.other_prop": 1}},
                                {"term": {"dates.other_prop": 4}}
                              ]
                            }
                          },
                          {
                            "bool": {
                              "must": [
                                {"term": {"dates.timestamp": 2}},
                                {"range": {"dates.rooms": {"lt": 5}}}
                              ],
                              "should": [
                                {"term": {"dates.other_prop": 1}},
                                {"term": {"dates.other_prop": 3}}
                              ]
                            }
                          }
                        ]
                      }
                    }
                  }
                }
              }
            }
          }
        }
      ]
    }
  }
}

推荐阅读