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

Elasticsearch嵌套排序

印宏阔
2023-03-14

我试图在Elasticsearch中进行嵌套排序,但到目前为止还没有成功。

我的数据结构:

{ "_id" : 1,
"authorList" : [
  {"lastName":"hawking", "firstName":"stephan"},
  {"lastName":"frey", "firstName":"richard"}
]
}

{ "_id" : 2,
"authorList" : [
  {"lastName":"roger", "firstName":"christina"},
  {"lastName":"freud", "firstName":"damian"}
]
}

我想根据文档中第一作者的姓氏对文档进行排序。

"authorList" : { "type" : "nested", "properties" : {"lastName":{"type":"keyword"}}}

使用SearchRequestBuilder(JAVA)进行排序:

    searchRequestBuilder.addSort(
SortBuilders.fieldSort("authorList.lastName")
.order(SortOrder.ASC)
.sortMode(SortMode.MIN)
.setNestedPath("authorList")
)

这是有效的,但不能给出想要的结果(例如,首先是“霍金”,然后是“罗杰”)。

我是不是漏掉了什么?是否有一种方法可以指示Elasticsearch访问数组authorlist的index=0?是否有任何映射/规范化程序来单独索引数组的第一个条目?

共有1个答案

斜和硕
2023-03-14

嵌套文档不保存为简单的数组或列表。它们由ElasticSearch内部管理:

Elasticsearch基本上仍然是扁平的,但它在内部管理嵌套关系,以给出嵌套层次结构的外观。创建嵌套文档时,Elasticsearch实际上索引了两个独立的文档(根对象和嵌套对象),然后在内部将这两个文档联系起来。(更多信息在此)

我认为您需要为elasticsearch提供一些额外的信息,这些信息将指示哪个作者是“主要/第一”作者。只将这个附加字段放在嵌套对象中的一个作者身上就足够了(映射可以保持以前的状态),类似如下:

{
    "authorList" : [
      {"lastName":"roger", "firstName":"christina", "authorOrder": 1},
      {"lastName":"freud", "firstName":"damian"}
    ]
},
{
    "authorList" : [
      {"lastName":"hawking", "firstName":"stephan", "authorOrder": 1},
      {"lastName":"adams", "firstName": "mark" }
      {"lastName":"frey", "firstName":"richard"}
    ]
},
{
    "authorList" : [
      {"lastName":"adams", "firstName":"monica", "authorOrder": 1},
      {"lastName":"adams", "firstName":"richard"}
    ]
}

则查询可以是:

{
  "query" : {
    "nested" : {
      "query" : {
        "bool" : {
          "must" : [
            {
              "match" : {
                "authorList.authorOrder" : 1
              }
            }
          ]
        }
      },
      "path" : "authorList"
    }
  },
  "sort" : [
    {
      "authorList.lastName" : {
        "order" : "asc",
        "nested_filter" : {
          "bool" : {
            "must" : [
              {
                "match" : {
                  "authorList.authorOrder" : 1
                }
              }
            ]
          }
        },
        "nested_path" : "authorList"
      }
    }
  ]
}

和Java API:

QueryBuilder matchFirst = QueryBuilders.boolQuery()
        .must(QueryBuilders.matchQuery("authorList.authorOrder", 1));
QueryBuilder mainQuery = QueryBuilders.nestedQuery("authorList", matchFirst, ScoreMode.None);

SortBuilder sb = SortBuilders.fieldSort("authorList.lastName")
    .order(SortOrder.ASC)
    .setNestedPath("authorList")
    .setNestedFilter(matchFirst);

SearchRequestBuilder builder = client.prepareSearch("test")
        .setSize(50)
        .setQuery(mainQuery)
        .addSort(sb);

请注意,SortBuilder具有.setnestedFilter(matchAll),这意味着排序基于authorlist.lastname字段,但仅基于“主要/第一”嵌套元素。没有它,elasticsearch将首先对所有嵌套文档进行排序,从升序排序列表中选择第一个元素,并在此基础上对父文档进行排序。因此,带有“霍金”的文件可以放在第一位,因为它有“亚当斯”的姓。

最终结果是:

"authorList" : [
      {"lastName":"adams", "firstName":"monica", "authorOrder": 1},
      {"lastName":"adams", "firstName":"richard"}
    ],
}
"authorList" : [
      {"lastName":"hawking", "firstName":"stephan", "authorOrder": 1},
      {"lastName":"adams", "firstName":"mark"},
      {"lastName":"frey", "firstName":"richard"}
    ]
},
{
    "authorList" : [
      {"lastName":"roger", "firstName":"christina", "authorOrder": 1},
      {"lastName":"freud", "firstName":"damian"}
    ]
}
 类似资料:
  • 问题内容: 我正在尝试在Elasticsearch中进行嵌套排序,但到目前为止没有成功。 我的数据结构: 我想根据文档中第一作者的姓氏对文档进行排序。 使用的映射: 使用SearchRequestBuilder(JAVA)进行排序: 这行得通,但没有给出想要的结果(例如,首先是“叫卖”,然后是“罗杰”)。 我错过了什么吗?有没有办法表明Elasticsearch访问数组authorList的ind

  • 我将Elasticsearch 6与PHP结合使用。 我的文档有一个嵌套字段,如下所示: 基本上每个文档都有很多价格,但我知道每个文档只有一个价格与过滤器/查询匹配。 我用它来搜索和排序,改编自这里的教程:https://www.elastic.co/guide/en/elasticsearch/guide/current/nested-sorting.html(对PHP数组格式表示抱歉): 我得

  • 问题内容: 我有以下ES内容,基本上是网站中包含嵌套商品的产品列表。 如何按站点详细信息的数量排序? tnx! 问题答案: 从问题的示例来看,它看起来像是单个文档,但是单个json文档不可能在同一级别具有相同名称的多个字段。 因此,假设每个字段代表一个不同的顶级文档

  • 我的索引中有以下类型的文档,但由于深度嵌套方面,我找不到正确排序的方法。 文档示例: 我希望排序或提升在匹配时间,以便我可以得到排序的文档(asc/desc)与约束和内嵌套文档和内嵌套文档

  • Sup社区。我有个问题。我正在使用Elasticsearch 6.4 我的数据结构的一部分: 我需要得到按成本排序的文档desc,我需要排序dirs字段中的值date_by字段与nulls-first。 如何对嵌套字段内的值进行排序,而不按此嵌套字段对文档进行排序?

  • 在这里,我得到了错误: “无效的术语聚合顺序路径[price>price>price.max]。术语桶只能在子聚合器路径上排序,该路径由路径中的零个或多个单桶聚合和路径末尾的最终单桶或度量聚合组成。子路径[price]指向非单桶聚合” 如果我按持续时间聚合排序,查询可以正常工作,如 那么,有什么方法可以通过嵌套字段上的嵌套聚合来排序聚合吗?