【问题标题】:Elasticsearch nested sortingElasticsearch 嵌套排序
【发布时间】:2018-01-16 02:48:08
【问题描述】:

我正在尝试在 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?是否有任何映射/规范化器来分别索引数组的第一个条目?

【问题讨论】:

    标签: java sorting elasticsearch nested


    【解决方案1】:

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

    Elasticsearch 基本上仍然是扁平的,但它管理嵌套 内部关系以给出嵌套层次结构的外观。什么时候 你创建一个嵌套文档,Elasticsearch 实际上索引了两个 单独的文档(根对象和嵌套对象),然后关联 两个内部。 (更多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"}
        ]
    }
    

    【讨论】:

    • 好的,这将解决问题。但是如果我必须引入一个新字段,那么创建一个字段“firstAuthorLastName”而不是复制第一个数组索引的值不是更容易吗?这也将简化查询/排序部分。
    • 是的,如果你可以这样重新排列你的模型,那么查询数据肯定会更容易。如果一个文件可以有例如idfirstAuthorLastNameotherAuthors 的嵌套列表,然后在顶级字段 firstAuthorLastName(而不是嵌套)上排序也会更快。
    猜你喜欢
    • 2016-09-06
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2019-10-25
    • 2013-01-08
    • 1970-01-01
    • 2019-05-24
    • 2019-05-29
    相关资源
    最近更新 更多