gpt4 book ai didi

java - Elasticsearch : Sorting by nested documents' values

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:02:48 24 4
gpt4 key购买 nike

我在为我的 Java 应用程序使用 ElasticSearch 时遇到了问题。我自己解释一下,我有一个映射,类似于:

{
"products": {
"properties": {
"id": {
"type": "long",
"ignore_malformed": false
},
"locations": {
"properties": {
"category": {
"type": "long",
"ignore_malformed": false
},
"subCategory": {
"type": "long",
"ignore_malformed": false
},
"order": {
"type": "long",
"ignore_malformed": false
}
}
},
...

因此,如您所见,我收到了一个由位置组成的产品列表。在我的模型中,这些位置都是类别的产品。这意味着一个产品可以属于一个或多个类别。在每个类别中,产品都有一个订单,这是客户想要向他们展示的订单。

比如钻石产品可以在Jewelry中排名第一,但在Woman中排名第三(我举的例子不太合逻辑^^)。因此,当我点击 Jewelry 时,我想显示此产品,按此特定类别中的字段 locations.order 排序。

目前,当我搜索特定类别的所有产品时,我收到的 ElasticSearch 响应类似于:

{"id":5331880,"locations":[{"category":5322606,"order":1},
{"category":5883712,"subCategory":null,"order":3},
{"category":5322605,"subCategory":6032961,"order":2},.......

是否可以根据我要搜索的特定类别的元素 locations.order 对这些产品进行排序?例如,如果我正在查询类别 5322606,我希望获得该产品的订单 1。

非常感谢您!问候,奥利维尔。

最佳答案

首先纠正术语:在 Elasticsearch 中,“父/子”指的是完全独立的文档,其中子文档指向父文档。父子存储在同一个分片上,但可以独立更新。

在上面的示例中,您尝试实现的目标可以通过嵌套 文档来完成。

目前,您的locations 字段是type:"object"。这意味着每个位置的值都被展平成如下所示:

{ 
"locations.category": [5322606, 5883712, 5322605],
"locations.subCategory": [6032961],
"locations.order": [1, 3, 2]
}

换句话说,“子”字段被扁平化为多值字段,这对您没有用,因为 category: 5322606order: 之间没有关联: 1

但是,如果您将 locations 更改为 type:"nested" 那么在内部它会将每个位置作为单独的文档进行索引,这意味着每个位置都可以独立查询, 使用专用的 nested queryfilter .

默认情况下,nested 查询将根据每个位置的匹配程度返回 _score,但在您的情况下,您希望返回 的最高值>order 来自任何匹配子项的字段。为此,您需要使用 custom_score查询。

所以让我们从创建具有适当映射的索引开始:

curl -XPUT 'http://127.0.0.1:9200/test/?pretty=1'  -d '
{
"mappings" : {
"products" : {
"properties" : {
"locations" : {
"type" : "nested",
"properties" : {
"order" : {
"type" : "long"
},
"subCategory" : {
"type" : "long"
},
"category" : {
"type" : "long"
}
}
},
"id" : {
"type" : "long"
}
}
}
}
}
'

我们索引您的示例文档:

curl -XPOST 'http://127.0.0.1:9200/test/products?pretty=1'  -d '
{
"locations" : [
{
"order" : 1,
"category" : 5322606
},
{
"order" : 3,
"subCategory" : null,
"category" : 5883712
},
{
"order" : 2,
"subCategory" : 6032961,
"category" : 5322605
}
],
"id" : 5331880
}
'

现在我们可以使用上面讨论的查询来搜索它:

curl -XGET 'http://127.0.0.1:9200/test/products/_search?pretty=1'  -d '
{
"query" : {
"nested" : {
"query" : {
"custom_score" : {
"script" : "doc[\u0027locations.order\u0027].value",
"query" : {
"constant_score" : {
"filter" : {
"and" : [
{
"term" : {
"category" : 5322605
}
},
{
"term" : {
"subCategory" : 6032961
}
}
]
}
}
}
}
},
"score_mode" : "max",
"path" : "locations"
}
}
}
'

注意:脚本中的单引号已转义为 \u0027 以绕过 shell 引用。该脚本实际上如下所示:"doc['locations.order'].value"

如果您查看结果中的 _score,您可以看到它使用了来自匹配的 locationorder 值:

{
"hits" : {
"hits" : [
{
"_source" : {
"locations" : [
{
"order" : 1,
"category" : 5322606
},
{
"order" : 3,
"subCategory" : null,
"category" : 5883712
},
{
"order" : 2,
"subCategory" : 6032961,
"category" : 5322605
}
],
"id" : 5331880
},
"_score" : 2,
"_index" : "test",
"_id" : "cXTFUHlGTKi0hKAgUJFcBw",
"_type" : "products"
}
],
"max_score" : 2,
"total" : 1
},
"timed_out" : false,
"_shards" : {
"failed" : 0,
"successful" : 5,
"total" : 5
},
"took" : 9
}

关于java - Elasticsearch : Sorting by nested documents' values,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14504180/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com