Elasticsearch запрос даты сортировки родительско-дочерних отношений (повторяющиеся события) - PullRequest
1 голос
/ 20 мая 2019

В настоящее время я работаю над приложением, в котором мы обрабатываем события. Итак, в Elasticsearch у нас есть документ с именем Event.

Раньше у нас было только одно событие (уникальное событие, происходящее 13 мая с 9 до 11 утра), сортировка была простой (сортировка по start_date с порядком)

Недавно мы добавили новую функцию, которая позволяет нам создавать повторяющиеся события, что означает, что теперь у нас есть 2 уровня внутри Elasticsearch (отношение родитель-потомок).

У нас может быть родительское событие с 12 мая по 14:00 до 14 мая с 18:00, связанное с этим событием, например, у нас есть дети, которые ежедневно. Таким образом, у нас было бы: 12 мая 2 вечера-6 вечера, 13 мая 2 вечера-6 вечера, 14 мая 2 вечера-6 вечера.

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

Я бы хотел провести сортировку, где ближайшая дата имеет более высокий приоритет. В этом случае уникальное событие должно быть первым в списке.

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

У меня нет большого опыта работы сasticsearch, поэтому я немного застрял, я видел много информации в документации (родитель-потомок, вложенные объекты, скрипты и т. Д.), Но я не знаю, как чтобы справиться с этим делом.

Я надеюсь, что я правильно объяснил, если у вас есть какие-либо вопросы, не стесняйтесь их задавать, я был бы рад предоставить вам дополнительную информацию.

Ответы [ 2 ]

0 голосов
/ 24 мая 2019

Первое, что вам следует учитывать, это то, что родительские и дочерние документы сохраняются отдельно. Это означает, что Parent-Event :: 1 и Child-Event :: 1 сохраняются в одном и том же сегменте (ES-маршруты направляются в раздел, где родительский элемент находится по хеш-идентификатору), но типы документов отличаются. Таким образом, вы должны получать родительские и дочерние документы отдельно по запросу и сортировать по дате. (Вы можете сделать следующие запросы в php, если работает)

П.С .: У меня тоже такая же ситуация, но мне пришлось реализовать на Java. Итак, я создал ES-конструктор запросов (https://github.com/mashhur/java-elasticsearch-querybuilder), который также поддерживает запросы отношения родитель-потомок, вы можете посмотреть ссылку.

// search child events and sort by date
GET events/_search {
"query": {
"has_parent": {
  "parent_type": "parent-event",
  "query": {
    "match_all": {}
   }
  },
  "sort": [{"start_date": {"desc"}}]
 }
}


// search parent events and sort by date
GET events/_search {
"query": {
"has_child": {
  "type": "child-event",
  "query": {
    "match_all": {}
   }
  },
  "sort": [{"start_date": {"desc"}}]
 }
}
0 голосов
/ 21 мая 2019

Для будущих гуглеров, вот как я это исправил.

Пришлось использовать скрипты и сортировать их, вот частичный пример запроса, который я использую

GET /event/_search
{
    "query" : {
      "match_all": {}
    },
    "sort" : {
        "_script" : {
            "type" : "number",
            "script": {
              "lang": "painless",
              "params": {
                "currentDate": 1560230000
              },
              "source": """
                def isRecurrenceParent = params._source.is_recurrence_parent;
                def countChildren = params._source.children.length;
                def currentDate = params.currentDate;

                if (isRecurrenceParent === false) {
                  return params._source.timestamp;
                }

                def nearest = 0;

                def lowestDiff = currentDate;

                for (int i = 0; i < countChildren; i++) {
                  def child = params._source.children[i];

                  def diff = child.timestamp - currentDate;
                  if (diff > 0 && diff < lowestDiff) {
                    lowestDiff = diff;
                    nearest = child.timestamp;
                  }
                }

                return nearest;
"""
            },
            "order" : "asc"
        }
    }
}
...