在Elasticsearch中基于匹配的内部嵌套对象对文档进行排序

5vf7fwbs  于 2023-10-17  发布在  ElasticSearch
关注(0)|答案(1)|浏览(108)

我正在对索引中的文档进行排序查询。下面是文件看起来像:

{
    "studentId": "123",
    "studentName": "Frodo",
    "year": "2023",
    "Scores": [{
            "subject": "Physics",
            "score": "100"
        },
        {
            "subject": "Chemistry",
            "score": "700"
        }
    ]
}
{
    "studentId": "456",
    "studentName": "Samwise",
    "year": "2023",
    "Scores": [{
            "subject": "Physics",
            "score": "200"
        },
        {
            "subject": "Chemistry",
            "score": "600"
        }
    ]
}
{
    "studentId": "789",
    "studentName": "Merry",
    "year": "2023",
    "Scores": [{
            "subject": "Physics",
            "score": "300"
        },
        {
            "subject": "Chemistry",
            "score": "500"
        }
    ]
}

我试图以降序方式获得福尔斯在范围内的结果。例如,我正在运行以下查询

{
    "size": 10000,
    "query": {
        "bool": {
            "must": [{
                    "term": {
                        "year": "2023"
                    }
                },
                {
                    "range": {
                        "Scores.score": {
                            "lte": 200
                        }
                    }
                }
            ]
        }
    },
    "sort": [{
        "Scores.score": {
            "order": "desc"
        }
    }]
}

与上述查询,我得到了2个文档的预期,但我得到的文档与'100'得分第一,而不是'200'.我认为当ES执行排序时,它首先拾取700个,然后拾取600个,并按此顺序给出文档。我如何做只对匹配的内部字段进行排序的查询?在这种情况下,排序应该只考虑200,100分,忽略其他。如果你能帮忙的话,我将不胜感激。谢谢你!
我已经尝试了min模式的排序模式选项。它适用于这个特定的例子,但它不适用于其他场景。例如,如果我在min模式下的同一个查询中使用800分,我会得到doc 3(300分和500分)作为响应,但我希望得到doc 1(100分和700分),因为700分是最高分。

jecbmhm3

jecbmhm31#

首先,我认为你有错误的Map。要做到这一点,“Scores”字段应该声明为nested。为了通过分数进行过滤,您需要使用nested query。最后,为了按照分数排序,你需要使用嵌套排序,使用与嵌套查询中相同的过滤器。如果你把所有这些合并组合在一起,你会得到这样的东西:

PUT test
{
  "settings": {
    "number_of_replicas": 0,
    "number_of_shards": 1
  },
  "mappings": {
    "properties": {
      "studentId": {
        "type": "long"
      },
      "studentName": {
        "type": "keyword"
      },
      "year": {
        "type": "long"
      },
      "Scores": {
        "type": "nested",
        "properties": {
          "subject": {
            "type": "keyword"
          },
          "score": {
            "type": "long"
          }

        }
      }
    }
  }
}

POST test/_bulk?refresh
{"index":{}}
{"studentId":"123","studentName":"Frodo","year":"2023","Scores":[{"subject":"Physics","score":"100"},{"subject":"Chemistry","score":"700"}]}
{"index":{}}
{"studentId":"456","studentName":"Samwise","year":"2023","Scores":[{"subject":"Physics","score":"200"},{"subject":"Chemistry","score":"600"}]}
{"index":{}}
{"studentId":"789","studentName":"Merry","year":"2023","Scores":[{"subject":"Physics","score":"300"},{"subject":"Chemistry","score":"500"}]}

POST test/_search
{
  "size": 10000,
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "year": "2023"
          }
        },
        {
          "nested": {
            "path": "Scores",
            "query": {
              "range": {
                "Scores.score": {
                  "lte": 200
                }
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "Scores.score": {
        "mode": "max",
        "order": "asc",
        "nested": {
          "path": "Scores",
          "filter": {
            "range": {
              "Scores.score": {
                "lte": 200
              }
            }
          }
        }
      }
    }
  ]
}

相关问题