В Elasticsearch, как отсортировать полученный результат по свойству вложенного поля

#elasticsearch

Вопрос:

В Elasticsearch предположим, что я создал users индекс. Этот индекс имеет внутреннее поле как вложенное, поэтому я могу рассматривать его как массив.

Пример вставленных данных:

 [{
        “isActive”: true,
        “id”: “0183284A-92BE-4CD7-8C76-98225562B4CB”,
        “actions”: [{
                “createdDate”: 1623895434,
                “userId”: “2B042D11-FD7E-4919-832A-ADBA3C63160C”,
                “type”: 0
            },
            {
                “createdDate”: 1623896475,
                “userId”: “4E3B2ACF-8D21-4CA8-865A-5A128873A6D9”,
                “type”: 0
            }
        ]
    },
    {
        “isActive”: true,
        “id”: “2B042D11-FD7E-4919-832A-ADBA3C63160C”,
        “actions”: [{
                “createdDate”: 1623805703,
                “userId”: “0183284A-92BE-4CD7-8C76-98225562B4CB”,
                “type”: 0
            },
            {
                “createdDate”: 1623895929,
                “userId”: “4E3B2ACF-8D21-4CA8-865A-5A128873A6D9”,
                “type”: 0
            }
        ]
    },
    {
        “isActive”: true,
        “id”: “4E3B2ACF-8D21-4CA8-865A-5A128873A6D9”,
        “actions”: [{
            “createdDate”: 1623893475,
            “userId”: “0183284A-92BE-4CD7-8C76-98225562B4CB”,
            “type”: 0
        }]
    }
] 
 

Итак, теперь скажите, что я вставил вышеуказанные 3 объекта в users индекс и сопоставил actions поле как вложенное.

Мне нужно иметь возможность выполнить запрос для извлечения всех пользователей, которые предприняли действия против другого пользователя:

 GET users/_search?pretty
{
  "query": {
    "bool": {
      "must": [
        {
          "nested": {
            "path": "actions",
            "query": {
              "bool": {
                "must": [
                  { "match": { "actions.userId.keyword": "4E3B2ACF-8D21-4CA8-865A-5A128873A6D9" }
                  }
                ]
              }
            },
            "inner_hits": { }
          }
        }
      ]
    }   
  }, 
  "_source": false
}
 

Таким образом, это вернет всех пользователей, у которых есть действия, включающие идентификатор пользователя = 4E3B2ACF-8D21-4CA8-865A-5A128873A6D9 :

 {
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.6931471,
        "hits": [{
                "_index": "users",
                "_type": "_doc",
                "_id": "0183284A-92BE-4CD7-8C76-98225562B4CB",
                "_score": 0.6931471,
                "inner_hits": {
                    "actions": {
                        "hits": {
                            "total": {
                                "value": 1,
                                "relation": "eq"
                            },
                            "max_score": 0.6931471,
                            "hits": [{
                                "_index": "users",
                                "_type": "_doc",
                                "_id": "0183284A-92BE-4CD7-8C76-98225562B4CB",
                                "_nested": {
                                    "field": "actions",
                                    "offset": 0
                                },
                                "_score": 0.6931471,
                                "_source": {
                                    "createdDate": 1623896475,
                                    "userId": "4E3B2ACF-8D21-4CA8-865A-5A128873A6D9",
                                    "type": 0
                                }
                            }]
                        }
                    }
                }
            },
            {
                "_index": "users",
                "_type": "_doc",
                "_id": "2B042D11-FD7E-4919-832A-ADBA3C63160C",
                "_score": 0.6931471,
                "inner_hits": {
                    "actions": {
                        "hits": {
                            "total": {
                                "value": 1,
                                "relation": "eq"
                            },
                            "max_score": 0.6931471,
                            "hits": [{
                                "_index": "users",
                                "_type": "_doc",
                                "_id": "2B042D11-FD7E-4919-832A-ADBA3C63160C",
                                "_nested": {
                                    "field": "actions",
                                    "offset": 0
                                },
                                "_score": 0.6931471,
                                "_source": {
                                    "createdDate": 1623895929,
                                    "userId": "4E3B2ACF-8D21-4CA8-865A-5A128873A6D9",
                                    "type": 0
                                }
                            }]
                        }
                    }
                }
            }
        ]
    }
}
 

Теперь я хочу отсортировать всех извлеченных пользователей на основе actions.createdDate . Как сделать подобное, пожалуйста?

Ответ №1:

script_score Подойдет ли вам здесь запрос? Мы бы по-прежнему требовали, чтобы запрос соответствовал вашему текущему идентификатору пользователя, но затем оценивали результаты на основе createdDate значения в части сценария.

 GET users/_search?pretty
{
  "query": {
    "nested": {
      "path": "actions",
      "query": {
        "script_score": {
          "query": {
            "match": { "actions.userId.keyword": "4E3B2ACF-8D21-4CA8-865A-5A128873A6D9" }
          },
          "script": {
            "source": "doc['actions.createdDate'].value"
          }
        }
      }
    }
  },
  "_source": false
}
 

Если это сработает , результаты будут отсортированы по убыванию createdDate , вы можете использовать обратную сортировку по возрастанию.