当前位置: 首页 > 知识库问答 >
问题:

ElasticSearch多级父子聚合

咸臻
2023-03-14

我有3个级别的父/子结构。假设:

公司-

由于这里经常更新可用性(以及员工),所以我选择对嵌套使用父/子结构。搜索功能工作正常(所有文档都在正确的碎片中)。

现在我想对这些结果进行排序。按公司(第1级)的元数据对它们进行排序很容易。但我也需要按第3级(可用性)进行排序。

我想要按以下顺序排列的公司列表:

  • 与给定ASC位置的距离
  • 评级DESC
  • 最快可用性ASC

例如:

A公司距离我们5英里,评分为4,最快一名员工在20小时内可以到达B公司距离我们5英里,也有评分为4,但最快一名员工在5小时内到达。

因此排序结果需要为B、A。

我想给每个数据附加特殊的权重,所以我开始编写聚合,稍后可以在我的custom_score脚本中使用。

创建索引、导入数据和搜索的全部要点现在,我已经编写了一个查询,它实际上返回结果,但可用性聚合桶是空的。然而,我也得到了过于结构化的结果,我想将其平铺。

目前我回来了:

公司ID-

我想有这样的聚合:

公司ID-

这样我就可以做我的custom_score脚本来计算分数并正确排序。

更简单的问题:
一个如何按多级(大)子级排序/聚合,并可能将结果展平。

共有2个答案

端木元青
2023-03-14

您应该检查R树数据结构https://en.wikipedia.org/wiki/R-tree.

卓雅达
2023-03-14

您不需要聚合来执行此操作:

以下是排序标准:

  1. 距离ASC(company.location)
  2. 评级DESC(company.rating_value)
  3. 最快的未来可用性ASC(company.employee.availability.start)

如果忽略#3,则可以运行相对简单的公司查询,如下所示:

GET /companies/company/_search
{
 "query": { "match_all" : {} },
 "sort": {
    "_script": {
        "params": {
            "lat": 51.5186,
            "lon": -0.1347
        },
        "lang": "groovy",
        "type": "number",
        "order": "asc",
        "script": "doc['location'].distanceInMiles(lat,lon)"
    },
    "rating_value": { "order": "desc" }
  }
}

#3很棘手,因为您需要向下寻找可用性(公司

我们将在孙子级别使用一个function\u score查询来计算请求时间和hit中每个可用性之间的时间差。(然后我们将使用评分作为第三个排序标准)。

要访问孙子,我们需要在has_child查询中使用has_child查询。

对于每家公司,我们都希望最快的可用员工(当然还有他们最接近的可用性)。对于这样的情况,Elasticsearch 2.0会给我们一个"score_mode":"min",但现在,由于我们仅限于"score_mode":"max",我们将使孙子孙女_score成为时差的倒数。

          "function_score": {
            "filter": { 
              "range": { 
                "start": {
                  "gt": "2014-12-22T10:34:18+01:00"
                } 
              }
            },
            "functions": [
              {
                "script_score": {
                  "lang": "groovy",
                  "params": {
                      "requested": "2014-12-22T10:34:18+01:00",
                      "millisPerHour": 3600000
                   },
                  "script": "1 / ((doc['availability.start'].value - new DateTime(requested).getMillis()) / millisPerHour)"
                }
              }
            ]
          }

因此,现在每个孙子(可用性)的得分将是1/可用小时数(这样我们可以使用每个员工可用的最大互惠时间和最大互惠时间(ly?)每个公司的可用员工)。

总而言之,我们继续查询company,但使用company

GET /companies/company/_search
{
 "query": { 
    "has_child" : {
        "type" : "employee",
        "score_mode" : "max",
        "query": {
          "has_child" : {
            "type" : "availability",
            "score_mode" : "max",
            "query": {
              "function_score": {
                "filter": { 
                  "range": { 
                    "start": {
                      "gt": "2014-12-22T10:34:18+01:00"
                    } 
                  }
                },
                "functions": [
                  {
                    "script_score": {
                      "lang": "groovy",
                      "params": {
                          "requested": "2014-12-22T10:34:18+01:00",
                          "millisPerHour": 3600000
                       },
                      "script": "1/((doc['availability.start'].value - new DateTime(requested).getMillis()) / millisPerHour)"
                    }
                  }
                ]
              }
            }
          }
        }
    }
 },
 "sort": {
  "_script": {
    "params": {
        "lat": 51.5186,
        "lon": -0.1347
    },
    "lang": "groovy",
    "type": "number",
    "order": "asc",
    "script": "doc['location'].distanceInMiles(lat,lon)"
  },
  "rating_value": { "order": "desc" },
  "_score": { "order": "asc" }
 }
}

 类似资料:
  • 问题内容: Book,User和Review说,我正在构建具有复杂模型的应用程序。 评论包含书籍和用户ID。为了能够搜索至少包含一个评论的“图书”,我已将“图书”设置为“评论”的父级,并且具有这样的路由。但是,我还需要找到撰写包含某些短语的评论的用户。 是否可以同时将书和用户作为评论的父级?有没有更好的方法来处理这种情况? 请注意,我无法更改数据建模的方式/不愿意这样做,因为数据已从持久性数据库传

  • 我知道Elasticsearch支持带bucketing的子聚合(其中bucketing聚合可以有bucketing或metric子聚合)。使用度量聚合无法进行子聚合。也许这是有道理的,但这里是用例。 作为家长,我有术语聚合。并将另一个术语聚合作为它的子项。子术语具有类型为top\u hits的子聚合

  • 我有一个描述容器的文档结构,它的一些字段是: 我想运行一个搜索聚合,该聚合在两个权重字段上有两个级别的术语聚合,但按权重字段的降序排列,如下所示: 样本文件: 预期输出(未完成): 但是,我不能按嵌套聚合排序。(错误:术语桶只能在子聚合器路径上排序,该子聚合器路径由路径中的零个或多个单桶聚合和最终的单桶或指标聚合构建...) 例如,对于上述示例输出,如果我在术语聚合上引入大小(如果我的数据很大,我

  • 问题内容: MYSQL返回一个数组,如下所示。我正在使用列:“ id_parent”自引用表以创建层次结构。因此,“ id”为2的条目可以是“ id_parent”为2的任何条目的父级,依此类推。 如何将子级嵌套在其父级数组中的数组中 问题答案: 引用具有顺序无关紧要的优点(子节点可以位于其父节点之前):

  • 问题是要确定子数据的总和是否等于父数据。如果是,返回真,否则返回假。 下面是我的代码,在提交时出现错误。我知道这是一个简单的问题,但在编写了条件之后,我很难通过遍历所有左右节点来递归检查二叉树中每个节点的和条件。 请指导我,因为我哪里做错了。

  • 我在elasticsearch中有一个文档索引,每个文档有480个字段。我试图做的是搜索一个词(例如“Apple”),并获得所有其值与搜索词匹配的唯一字段名。所以如果我的文档是: 作为查询的结果,我希望得到如下所示的聚合: 由于每个文档都有480个字段,所以我更喜欢执行multi_match查询,而不是使用包含所有字段的筛选器: 这个查询在ElasticSearch中可能吗?