Сортировка Elasticsearch по: наличию элемента в массиве и дате

#elasticsearch #elasticsearch-5

#elasticsearch #elasticsearch-5

Вопрос:

Я хочу создать запрос на версии 5.6, где я нахожу все книги, которые:

  • принадлежат пользователю или помечены этим пользователем как избранные
  • а затем отсортируйте их по тому факту, что они являются его любимыми первыми и последующими по дате. Запись в книге будет выглядеть следующим образом
 {
  title: "book1"
  users_favourite: ["1", "2"],
  userid: "1",
  date: timestamp
}
 

У меня есть большая часть запросов, но я не знаю, как поместить любимые книги сверху и отсортировать по дате:

 {
  "from" : 0,
  "size" : 51,
  "query" : {
    "bool" : {
      "should" : [
        {
          "match" : {
            "users_favourite" : {
              "query" : "1",
              "operator" : "OR"
            }
          }
        },
        {
          "term" : {
            "userid" : {
              "value" : "1"
            }
          }
        }
      ]
    }
  },
  "sort" : [
    {
      "date" : {
        "order" : "desc",
        "missing" : "_last",
        "unmapped_type" : "string"
      }
    }
  ]
}
 

Таким образом, результат будет следующим: сначала все любимые книги пользователей, отсортированные по дате
, за которыми следуют книги, принадлежащие этому пользователю, также упорядоченные по дате.

избранное пользователя Дата
верно 2021
верно 2020
верно 2018
ложь 2021
ложь 2019
ложь 2017

Комментарии:

1. 1. Каков тип сопоставления для «users_favourite «? 2. Может ли запрос искать несколько «users_favourite» или только один? 3. Может ли «users_favourite» быть пустым?

2. 1. сопоставление users_favourite является ключевым словом 2. Я всегда запрашиваю одного пользователя 3. да, users_favourite cab должен быть пустым

Ответ №1:

Общее решение, которое я бы использовал, выглядит примерно так

Что касается сортировки:

 GET social_unique_flat_verified_guesses/_search
{
  "from": 0,
  "size": 51,
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "users_favourite": {
              "query": "1",
              "operator": "OR"
            }
          }
        },
        {
          "term": {
            "userid": {
              "value": "1"
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "_script": {
        "type": "number",
        "script": {
          "lang": "painless",
          "source": "doc['users_favourite'].contains(params.users_favourite) ? 1 : 0",
          "params": {
            "users_favourite": "1"
          }
        },
        "order": "desc"
      }
    },
    {
      "date": {
        "order": "desc",
        "missing": "_last",
        "unmapped_type": "string"
      }
    }
  ]
}
 

Это указывает elastic сначала оценить все совпадающие (1 или 0), если книга находится в избранном пользователем, а затем по годам.

Кроме того, я бы изменил предложение should для избранного пользователя на это

 "term": {
      "users_favourite": {
        "value": "1"
      }
    }
 

Имейте в виду, что если поле «users_favourite» может быть пустым, или если запрос может выполнять поиск по нескольким избранным пользователем, запрос должен быть немного другим. Так что дайте мне знать, и я отредактирую его

Комментарии:

1. Спасибо @ron-serruya, это решение работает. Одно из изменений, которое я должен был сделать, это удалить значение, чтобы источником был «doc[‘users_favourite’].contains(params.users_favourite) ? 1 : 0»

2. @rPawel Да, вы правы, .value принимает первый индекс вместо всего списка