Parse.com 'retweet' шаблон слишком многословный
Итак, мне было поручено реализовать в приложении (iOS, Swift) функциональность "retweet", используя Parse.
Это было задано до здесь, но это a) довольно высокий уровень и b) я получаю задание под рукой - я не обязательно прошу помощи архитектурные решения, хотя, если кажется, что я, очевидно, чего-то не хватает, я рад принять обратную связь.
В моем приложении есть ПРИЧИНЫ, которые создаются пользователем.
Существует также таблица FOLLOW с пользователем TO и FROM.
Поэтому для начала я просто запрашиваю таблицу CAUSES с ограничением, которое USER, который разместил, должен соответствовать объектуId пользователя TO (где текущий пользователь является пользователем FROM) в таблице FOLLOW. Более кратко:
let getFollowedUsersQuery = PFQuery(className: Constants.kParseClassFollowers)
getFollowedUsersQuery.whereKey(Constants.kParseFieldFromUser, equalTo: PFUser.currentUser()!)
let causesQuery = PFQuery(className: Constants.kParseClassCauses)
causesQuery.whereKey(Constants.kParseFieldFromUser, matchesKey: Constants.kParseFieldToUser, inQuery: getFollowedUsersQuery)
causesQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let causes = objects {
for cause in causes {
// populate the tableview cells, etc.
}
}
})
Теперь у меня есть все причины от пользователей, за которыми я следую... что все довольно стандартно.
Здесь, где это становится сложно.
Каждая ПРИЧИНА также имеет отношение, называемое SUPPORTERS.
Теперь мне нужно архивировать способ получить все ПРИЧИНЫ от людей, за которыми я не следую, но которые имеют в своем списке сторонников пользователя, которого я придерживаюсь.
Мне еще предстоит найти элегантное решение, хотя я приближаюсь к "грубой силе", и это настолько громоздко и многословно, что лучшая половина моего мозга программиста кричит на меня, как Сьюзан Паутер...
Здесь пример:
let retweetQuery = PFQuery(className: Constants.kParseClassCauses)
retweetQuery.orderByDescending(Constants.kParseFieldCreatedAt)
retweetQuery.whereKey(Constants.kParseFieldFromUser, notEqualTo: PFUser.currentUser()!)
retweetQuery.whereKey(Constants.kParseFieldFromUser, doesNotMatchKey: Constants.kParseFieldToUser, inQuery: getFollowedUsersQuery)
retweetQuery.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if let causes = objects {
for cause in causes {
let supporterRelations = cause.relationForKey(Constants.kParseClassSupporters)
let supporterQuery = supporterRelations.query()
supporterQuery.findObjectsInBackgroundWithBlock { (supporters, error) in
if(error == nil && supporters?.count > 0) {
for supporter in supporters! {
let user:PFUser = supporter as! PFUser
getFollowedUsersQuery.whereKey(Constants.kParseFieldToUser, equalTo: user)
getFollowedUsersQuery.whereKey(Constants.kParseFieldFromUser, equalTo: PFUser.currentUser()!)
getFollowedUsersQuery.findObjectsInBackgroundWithBlock({ (results, error) -> Void in
if(error == nil && results?.count > 0) {
for result in results! {
// do stuff
}
}
})
}
}
}
}
}
})
Теперь это чистое безумие и невероятно расточительное (особенно учитывая, как Parse вычисляет свободный уровень), я считаю, что это может действительно сильно повлиять на мой лимит API, если оно будет перенесено на производство).
Уже выполнив два запроса, я полностью переделаю их, затем выполним другой запрос для каждой причины в отношениях SUPPORTER, затем выполните другой запрос для каждого пользователя в этом отношении, чтобы увидеть, следую ли я им... и как только я мне нужно пройти через поддерживаемые пользователем причины (из-за асинхронного возвращения запросов Parse я не чувствую, что могу просто вернуться обратно в родительские петли), которые я еще не реализовал, потому что я собираюсь бросить полотенце - должен быть лучший способ!
Я надеюсь, что здесь отсутствует стратегия...
Ответы
Ответ 1
@jesses.co.tt Прошу прощения, если это слишком поздно, я определенно хочу отметить, что я отвечаю в эти месяцы после того, как его спросили, но я думаю, что это стоит ответить вообще (и, возможно, по-прежнему будет полезен для вас).
В общем, я на 100% согласен с тем, что этот тройной запрос с Parse: a) будет массово неэффективным, как он выставил счет (в старой системе) и b) с учетом этого, кажется неправильным подходом даже с самим собой -hosted Parse (который контекстуально является единственным механизмом, который можно использовать в этот момент, поскольку Parse теперь закрыт, но я думаю, что все еще возможно, когда был задан вопрос... независимо...). Есть два решения, которые я вижу, которые могут исправить это довольно чистым способом, предполагая, что эти изменения могут быть внесены в общую схему/архитектуру.
1)
Первым решением является повторная схематизация набора данных и по существу "внешнего ключа" подмножества сторонников, каждый из которых User
имеет в самой таблице User
. Таким образом, вместо перехода от Cause
→ Supporter
→ User
теоретически вы сможете сделать Cause
→ User
(где от пользователей вы получите своих сторонников по умолчанию так как это будет колонка). Чтобы сделать это в Parse
, если я правильно помню, вы можете установить для столбца массив определенного типа в качестве значения, а затем иметь object
ссылки (которые хорошо отображаются в панель инструментов Parse), которые являются фактическими объектами таблицы Supporter
, но сохраняя этот столбец ссылок на эту таблицу в таблице User
.
Пока немного работаем над стороной write
, так как вам придется вручную сделать это (вручную я имею в виду написать код самостоятельно, чтобы это сделать, оно должно быть автоматизировано, но это не произойдет бесплатно с точки зрения развития). С помощью этой немного более предварительной операции write
у вас будет 2 шаг read
вместо 3.
2). Второе решение - использовать другой поставщик данных такого типа, если проблема с запросами. В нескольких моих проектах я использую подходы на основе сокетов для такого поиска запросов к данным и думает, что Pusher или Firebase (оба очень разных уровня "все включено", Firebase, гораздо больше похоже на "Анализ", но из Google на этот раз Pusher будет немного более базовым и "сделай сам" ).
С Firebase, например, и сокет в этот набор данных + схема, в которой сама таблица Cause
имеет кэш того, что User
принадлежит им (и в котором User
имеет кэш своих Supporter
s), этот трехэтапный поиск может эффективно быть 1 запросом с 2 параметрами (которые я думаю, идеальный сценарий). Я считаю, что это может быть достигнуто и с помощью Parse, но для первого предлагаемого решения потребуется другой этап реорганизации схемы.
Я думаю, что в комментариях рекомендуется нечто подобное этому (оба решения выше), но в гораздо более непроработанном формате. Надеюсь, это поможет первопроходцу или кому-то другому. Теоретически, теоретически, как рекомендовал кто-то, используйте PubNub как упоминалось 1 комментарий, но это могло бы просто как легко построить эту схему в БД PostgreSQL, размещенную на AWS или Heroku, и выполните те же самые механизмы, что и Parse без накладных расходов.
Кроме того, поскольку это относится к Parse, который теперь предлагается только как самоорганизованное решение с открытым исходным кодом, вот руководство по переносу на хостинг Parse на своем собственном сервере AWS: здесь