java - Elasticsearch 嵌套排序

标签 java sorting elasticsearch nested

我正在尝试在 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")
)

这行得通,但没有给出想要的结果(例如,先是“hawking”,然后是“roger”)。

我错过了什么吗?有没有办法指示 Elasticsearch 访问数组 authorList 的 index=0?是否有任何映射/规范化器来单独索引数组的第一个条目?

最佳答案

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

Elasticsearch is still fundamentally flat, but it manages the nested relation internally to give the appearance of nested hierarchy. When you create a nested document, Elasticsearch actually indexes two separate documents (root object and nested object), then relates the two internally. (more here)

我认为您需要向 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 将首先对所有嵌套文档进行排序,从升序排序列表中选择第一个元素,并基于此对父文档进行排序。因此带有“Hawking”的文档可能排在第一位,因为它的姓氏是“Adams”。

最终结果是:

"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"}
    ]
}

关于java - Elasticsearch 嵌套排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45569898/

相关文章:

java - 通过嵌套列表对象中的多个值查找对象 Hibernate、Jpa

ruby-on-rails - Rails elasticsearch搜索嵌套的json字段

elasticsearch - 聚合热门点击 ElasticSearch

linux - 我如何强制排序命令将 'ADNP-AS1' 放在 'ADNP2' 之后,而不是相反?

elasticsearch - Elasticsearch :匹配其数组包含此字段的文档

java - ImapIdleChannelAdapter 未获取消息内容

java - 从 arraylist 创建 3 列 html 表?

java - 将 Java Web 服务 WSDL 与 gsoap C 客户端一起使用时出现标记不匹配错误

python - 如何在 Python 中使用基数排序按字母顺序对(很长)对象列表进行排序?

javascript - 按 3 个键排序 - Javascript