代码之家  ›  专栏  ›  技术社区  ›  LaserJesus

如何基于Elasticsearch中的rescore函数选择顶级术语bucket

  •  3
  • LaserJesus  · 技术社区  · 6 年前

    {
      "size": 0,
      "query": {
        "match_all": {}
      },
      "rescore": [
        {
          "window_size": 10000,
          "query": {
            "rescore_query": {
              "function_score": {
                "boost_mode": "replace",
                "script_score": {
                  "script": {
                    "source": "doc['topic_score'].value"
                  }
                }
              }
            },
            "query_weight": 0,
            "rescore_query_weight": 1
          }
        }
      ],
      "aggs": {
        "distinct": {
          "terms": {
            "field": "identical_id",
            "order": {
              "top_score": "desc"
            }
          },
          "aggs": {
            "best_unique_result": {
              "top_hits": {
                "size": 1
              }
            },
            "top_score": {
              "max": {
                "script": {
                  "inline": "_score"
                }
              }
            }
          }
        }
      }
    }
    

    这是一个简化的版本,其中实际查询有一个更复杂的主查询,而rescore函数要密集得多。

    identical_id . 如果有更好的方法,我也会认为这是一个答案。

    我希望这样的查询会按rescore查询对结果进行排序,将具有相同结果的所有结果分组 并显示每个不同组的最高点击率。我还假设,因为我是按最大父级排序这些术语聚合桶的 _score ,它们将被命令反映它们所包含的最佳结果,这些结果是根据原始重新存储查询确定的。

    实际上,术语bucket是按最大查询分数排序的,而不是按重新存储查询分数排序的。奇怪的是,桶内的顶部点击似乎确实使用了重新扫描。

    有没有更好的方法来实现我想要的最终结果,或者有什么方法可以修复这个查询,使其以我期望的方式工作?

    2 回复  |  直到 6 年前
        1
  •  2
  •   Pierre Mallet    6 年前

    documentation

    查询重新排序器仅对前K个结果执行第二个查询 由查询和后期筛选阶段返回 . 每个shard上要检查的文档数可以由window\u size参数控制,该参数默认为10。

    作为 rescore query post_filter 阶段,我假设术语聚合桶已经固定。

    我不知道如何将重新存储和聚合结合起来。对不起:(

        2
  •  1
  •   LaserJesus    6 年前

    我认为我有一个很好的解决这个问题的办法,但我会让悬赏继续到期,以防有人想出更好的办法。

    {
      "size": 0,
      "query": {
        "match_all": {}
      },
      "aggs": {
        "sample": {
          "sampler": {
            "shard_size": 10000
          },
          "aggs": {
            "distinct": {
              "terms": {
                "field": "identical_id",
                "order": {
                  "top_score": "desc"
                }
              },
              "aggs": {
                "best_unique_result": {
                  "top_hits": {
                    "size": 1,
                    "sort": [
                      {
                        "_script": {
                          "type": "number",
                          "script": {
                            "source": "doc['topic_score'].value"
                          },
                          "order": "desc"
                        }
                      }
                    ]
                  }
                },
                "top_score": {
                  "max": {
                    "script": {
                      "source": "doc['topic_score'].value"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    

    这个 sampler 聚合将从核心查询中获取每个碎片的前N个命中数,并在这些命中数上运行聚合。然后在定义bucket order的max aggregator中,我使用的脚本与从bucket中选取热门内容的脚本完全相同。现在bucket和top hits在相同的前N个项目集上运行,bucket将按同一脚本生成的相同得分的最大值排序。不幸的是,我仍然需要运行一次脚本来排序bucket,并在bucket中选择一个top hit,您可以使用rescore来代替top hits排序,但无论哪种方式,它都必须运行两次,我发现作为排序脚本比作为rescore运行更快