Фильтровать документы, используя 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
- Сделайте массив с альбомами в
SELECT
утверждение с помощьюarray_agg()
функция; - использование
ARRAY_SORT()
отсортировать этот массив по определенному полю (album.creationDate
). Эта функция сортирует только вASC
порядок. - использование
ARRAY_REVERSE()
отменить заказ, чтобы получить последний альбом