Можете ли вы объединить денормализованные результаты запроса сервера синтаксического анализа в один оператор, используя Swift? - PullRequest
0 голосов
/ 09 мая 2019

Мой опыт работы с SQL, но я работаю над изучением управления данными сервера синтаксического анализа, и в примере ниже я демонстрирую, как я буду использовать SQL для представления данных, которые в настоящее время хранятся в моих классах сервера синтаксического анализа. Я пытаюсь представить всех пользователей, количество загруженных ими изображений и количество понравившихся им изображений для приложения, в которое пользователи могут загружать изображения, а также могут просматривать и просматривать изображения других людей. Я сохраняю идентификатор пользователя, который загрузил изображение в таблицу изображений, и храню столбец массива в таблице изображений всех идентификаторов, которые ему понравились.

Используя SQL, я бы нормализовал это в 3 таблицы (user, image, user_x_image), присоединился к таблицам и затем агрегировал этот результат. Но я пытаюсь найти правильный способ сделать это, используя сервер синтаксического анализа, где я понимаю, что лучше всего структурировать данные, как у меня ниже. То, что я хочу сделать, это создать «таблицу лидеров», которая представляет, какие пользователи загрузили больше всего изображений или понравились больше всего изображений, чтобы вдохновить участие. Даже полезные ссылки на примеры того, как объединять / объединять наборы данных анализа, были бы очень полезны. Если мне непонятно, чего я добиваюсь, сообщите мне, если я оставлю комментарии, и я добавлю обновления.

-- SQL approximation of data structured in parse
create volatile table users
( user_id char(10)
, user_name char(50)
) on commit preserve rows;
insert into users values('1a','Tom');
insert into users values('2b','Dick');
insert into users values('3c','Harry');
insert into users values('4d','Simon');
insert into users values('5e','Garfunkel');
insert into users values('6f','Jerry');

create volatile table images
( image_id char(10)
, user_id_owner char(10) -- The object Id for the parse user that uploaded
, UsersWhoLiked varchar(100) -- in Parse class this is array of user ids that clicked like
) on commit preserve rows;
insert into images values('img01','1a','["4d","5e"]');
insert into images values('img02','6f','["1a","2b","3c"]');
insert into images values('img03','6f','["1a","6f",]');
-----------------------------
-- DESIRED RESULTS
-- Tom has 1 uploads and 2 likes 
-- Dick has 0 uploads and 1 likes
-- Harry has 0 uploads and 1 likes
-- Simon has 0 uploads and 1 likes
-- Garfunkel has 0 uploads and 1 likes
-- Jerry has 2 uploads and 1 likes

-- How to do with normalized data structure
create volatile table user_x_image
( user_id char(10)
, image_id char(10)
, relationship char(10)
) on commit preserve rows;
insert into user_x_image values('4d','img01','liker');
insert into user_x_image values('5e','img01','liker');
insert into user_x_image values('1a','img02','liker');
insert into user_x_image values('2b','img02','liker');
insert into user_x_image values('3c','img02','liker');
insert into user_x_image values('1a','img03','liker');
insert into user_x_image values('6f','img03','liker');

-- Return the image likers/owners
sel
  a.user_name
, a.user_id
, coalesce(c.cnt_owned,0) cnt_owned
, sum(case when b.relationship='liker' then 1 else 0 end) cnt_liked
from
  users        A
left join
  user_x_image B
  on a.user_id = b.user_id
left join (
  sel user_id_owner, count(*) as cnt_owned
  from images
  group by 1) C 
  on a.user_id = c.user_id_owner
group by 1,2,3 order by 2
-- Returns desired results

1 Ответ

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

Во-первых, я предполагаю, что вы используете Parse Server с базой данных MongoDB (Parse Server также поддерживает Postgres, и это может немного упростить реляционные запросы).В связи с этим важно отметить, что помимо того, что Parse Server реализует реляционные возможности в своем API, на самом деле речь идет о базе данных NoSQL за кулисами.Итак, давайте перейдем к опциям.

Вариант 1 - денормализованные данные

Поскольку это база данных NoSQL, я бы предпочел иметь третью коллекцию под названием LeaderBoard.Вы можете добавить триггер afterSave к классу UserImage и сделать LeaderBoard всегда обновленным.Когда вам нужны данные, вы можете сделать очень простой и быстрый запрос.Я знаю, что для опытного разработчика SQL странно иметь денормализованные данные, но это лучший вариант с точки зрения производительности, если в этой коллекции больше операций чтения, чем записи.

Вариант 2- Aggregate

MongoDB поддерживает агрегаты (https://docs.mongodb.com/manual/aggregation/) и имеет этап конвейера с именем $ lookup (https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/)), который можно использовать для выполнения запроса с использованием одногоОперация вызова API / базы данных. Parse Server также поддерживает агрегаты в своем API и JS SDK (https://docs.parseplatform.org/js/guide/#aggregate), но, к сожалению, не напрямую из клиентского кода в Swift, поскольку для этой операции требуется главный ключ на сервере Parse. Поэтому вам потребуетсянаписать функцию облачного кода, которая выполняет агрегатный запрос для вас, а затем вызвать эту функцию облачного облака из вашего клиентского кода Swift.

...