Фильтровать документы, используя n1ql

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

Тип документа (певец):

{
  "id":"223-34fd-35325-dsf-343f",
  "resourceType":"Singer",
  "name":"Paul"
}

Тип документа (Альбом1):

{
   "id":"456-d435-43g346-43-436tf-345g",
   "name":"Amazing night",
   "author":"223-34fd-35325-dsf-343f",
   "creationDate": "2017-05-12T07:57:51.458Z"
}

Тип документа (Альбом2):

{
   "id":"878-ffe6-43gs56-5hn7-ffgdd-345hd",
   "name":"Be quiet",
   "author":"223-34fd-35325-dsf-343f",
   "creationDate": "2017-05-11T13:43:05.580Z"
}

Ну, мне нужно получить список певцов только с одним альбомом (который был добавлен последним, основываясь на creationDate). В моем случае мне нужно достать певца "Пола" и альбом "Удивительная ночь". Возможно ли это?

3 ответа

Решение

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

SELECT singer, MAX([a.creationDate, a])[1] latestAlbum
FROM default a
WHERE a.author IS NOT MISSING
GROUP by a.author
LETTING singer = (SELECT RAW s.name FROM default s USE KEYS a.author)[0];

Конечно, это возможно.. Попробуйте этот запрос:

SELECT singer, 
       FIRST x.name FOR x IN ARRAY_AGG({a.creationDate, a.name}) 
                    WHEN x.creationDate = max(a.creationDate) END 
       AS latestAlbum
FROM default a
WHERE a.author IS NOT MISSING
GROUP by a.author
LETTING singer = (SELECT RAW s.name FROM default s USE KEYS a.author)[0];

Большая часть волшебства заключается в выражении "FIRST" N1QL в проекции, которая вычисляет последний альбом. Вот,

  • выражение ARRAY_AGG({...}) динамически создает массив объектов с именем createDate и альбома для каждого исполнителя (из GROUP BY)
  • выражение FIRST возвращает первый такой элемент в вышеуказанном массиве, который соответствует условию WHEN, со значением MAX creationDate. Обратите внимание, что используемый вами формат даты находится в лексическом порядке сортировки, поэтому нам не требуется никакой обработки формата даты для сортировки значений даты.
  • имя певца получается с помощью подзапроса в классе LETTING

Кстати, вы можете использовать конструкцию ARRAY (вместо FIRST), если вы хотите получить все последние альбомы с одинаковым creationDate

   ARRAY x.name FOR x IN ARRAY_AGG({a.creationDate, a.name}) 
                WHEN x.creationDate = max(a.creationDate) END 
   AS latestAlbum

Ура!!

Я также нашел вариант, чтобы получить последний альбом:

SELECT singer.name as singertName, ARRAY_REVERSE(ARRAY_SORT(array_agg(album.creationDate)))[0] as album from bucket where type='album' and album.author = "223-34fd-35325-dsf-343f" group by album.author order by album.author

  1. Сделайте массив с альбомами в SELECT утверждение с помощью array_agg() функция;
  2. использование ARRAY_SORT() отсортировать этот массив по определенному полю (album.creationDate). Эта функция сортирует только в ASC порядок.
  3. использование ARRAY_REVERSE() отменить заказ, чтобы получить последний альбом
Другие вопросы по тегам