【问题标题】:ElasticSearch sorting isn't sorting by fieldElasticSearch 排序不是按字段排序
【发布时间】:2021-04-01 05:06:40
【问题描述】:

我正在尝试对指定字段执行字段排序,但无济于事。当我运行脚本时,查询一直返回相同的位置。

这是 ElasticSearch 脚本:

{
  "from": 0,
  "size": 10,
  "timeout": "60s",
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "must": [
              {
                "query_string": {
                  "query": "random",
                  "fields": [],
                  "type": "best_fields",
                  "default_operator": "or",
                  "max_determinized_states": 10000,
                  "enable_position_increments": true,
                  "fuzziness": "AUTO",
                  "fuzzy_prefix_length": 0,
                  "fuzzy_max_expansions": 50,
                  "phrase_slop": 0,
                  "escape": false,
                  "auto_generate_synonyms_phrase_query": true,
                  "fuzzy_transpositions": true,
                  "boost": 1
                }
              },
              {
                "nested": {
                  "query": {
                    "bool": {
                      "must": [
                        {
                          "match": {
                            "reviews.source": {
                              "query": "TEST",
                              "operator": "AND",
                              "prefix_length": 0,
                              "max_expansions": 50,
                              "fuzzy_transpositions": true,
                              "lenient": false,
                              "zero_terms_query": "NONE",
                              "auto_generate_synonyms_phrase_query": true,
                              "boost": 1
                            }
                          }
                        }
                      ],
                      "adjust_pure_negative": true,
                      "boost": 1
                    }
                  },
                  "path": "reviews",
                  "ignore_unmapped": false,
                  "score_mode": "avg",
                  "boost": 1,
                  "inner_hits": {
                    "name": "reviews",
                    "ignore_unmapped": false,
                    "from": 0,
                    "size": 3,
                    "version": false,
                    "seq_no_primary_term": false,
                    "explain": false,
                    "track_scores": false
                  }
                }
              }
            ],
            "adjust_pure_negative": true,
            "boost": 1
          }
        }
      ],
      "should": [
        {
          "match": {
            "dataset": {
              "query": "QUERY_TEST",
              "operator": "OR",
              "prefix_length": 0,
              "max_expansions": 50,
              "fuzzy_transpositions": true,
              "lenient": false,
              "zero_terms_query": "NONE",
              "auto_generate_synonyms_phrase_query": true,
              "boost": 1
            }
          }
        }
      ],
      "adjust_pure_negative": true,
      "minimum_should_match": "1",
      "boost": 1
    }
  },
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    },
    {
      "reviews.openedAt": {
        "order": "desc",
        "nested": {
          "path": "reviews"
        }
      }
    }
  ]
}

我目前使用的映射:

"reviews": {
        "type": "nested",
        "properties": {
          "id": {
            "type": "keyword",
            "copy_to": "fulltext"
          },
          "updatedAt": {
            "type": "date",
            "format": "strict_date_time",
            "index": false
          },
          "openedAt": {
            "type": "date",
            "format": "strict_date_time"
          }

我正在尝试根据评论部分中的特定日期对记录进行排序。如果用户输入 ASC,则返回值(评论)应基于 openAt 日期按升序排列。我相信排序功能不一定会到达适当的路径。排序函数应该是什么样子的?

我创建了一个调用请求并创建自己的记录集的 Java API:

public SearchResponse(SearchResponse response, SearchRequest searchRequest) {
        this.facets = new ArrayList<>();
        if (searchRequest == null || searchRequest.getRestricted().isEmpty()) {
            this.records =
              Stream.of(response.getHits().getHits()).map(SearchHit::getSourceAsMap).collect(Collectors.toList());
        } else {
            this.records = processRestrictedResults(response, searchRequest);
        }
        if (response.getAggregations() != null) {
            for (Map.Entry<String, Aggregation> entry : response.getAggregations().getAsMap().entrySet()) {
                this.facets.add(Facet.create(entry));
            }
        }
        this.totalRecords = getTotalMatched(response);
}

【问题讨论】:

  • 压缩后的响应与您预期的效果相比如何?
  • 这是带有 2 条记录的压缩响应的样子:1:"reviews": [{ "assignedTo": "Anna D. Analyst", "openedAt": "2021-03-30T08:13:53.552Z", "updatedAt": "2021-03-03T11:22:33.123Z", }] 2:"reviews": [{ "assignedTo": "Anna D. Analyst", "openedAt": "2021-03-06T08:13:53.552Z", "privateComment": "", "updatedAt": "2021-03-03T11:22:33.123Z" }, { "assignedTo": "Kevin D. Analyst", "openedAt": "2021-04-06T08:13:53.552Z", "updatedAt": "2021-03-03T11:22:33.123Z } 我希望响应根据 openAt 字段按降序排序

标签: java elasticsearch


【解决方案1】:

为了回答最初的问题,顶级点击确实按照最新的reviews.openedAt 降序排列 — 来自 doc#2 的评论之一的值为 2021-04-06T08:13:53.552Z这大于来自 doc#1 (2021-03-30T08:13:53.552Z) 的唯一 reviews.openedAt,因此 #2 在 #1 之前。

不过,您缺少的是sorted inner_hits,正如我解释过的herehere

在您的特定用例中,这意味着:

{
  "from": 0,
  "size": 10,
  "timeout": "60s",
  "query": {
    "bool": {
      "must": [
        ...                        // your original queries
        {
          "nested": {
            "path": "reviews",     <-- we need to enforce the nested context
            "query": {
              "match_all": {}      <-- this could've been `"exists": { "field": "reviews.openedAt" }` too 
            },
            "inner_hits": {
              "sort": {
                "reviews.openedAt": {    <-- sorting the inner hits under the nested context
                  "order": "desc"
                }
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "_score": {
        "order": "desc"
      }
    },
    {
      "reviews.openedAt": {   <-- sorting the top-level hits, as you previously were
        "order": "desc",
        "nested": {    
          "path": "reviews"
        }
      }
    }
  ]
}

当您运行上述查询时,每个顶级命中都将包含一个 inner_hits 属性,其中包含已排序的 reviews,然后您可以在您的 java 后端对其进行后处理。

【讨论】:

    猜你喜欢
    • 2016-01-26
    • 1970-01-01
    • 2021-01-30
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多