#swift #firebase #google-cloud-firestore
#swift #firebase #google-облако-firestore
Вопрос:
У меня есть приложение firebase, которое включает в себя коллекцию, содержащую записи, которые были созданы в приложении, каждая с документом, содержащим данные для записи. Как пользователь, вы можете поставить лайк на публикацию, и идентификаторы ваших понравившихся записей сохраняются в пользовательском документе. В прошлом приложении я хочу иметь возможность извлекать все сообщения, которые понравились пользователю. У меня есть два способа сделать это:
Первый вариант, который я мог бы использовать для параметра where field:
static func getLikedPosts(likedIDs: [String], completion: @escaping ((_ data: [Post]) -> Void)) {
db.collection("posts").whereField("postID", in: likedIDs).getDocuments {(querySnapshot, err) in
if let err = err {
print(err)
} else {
var listings: [Listing] = []
for doc in querySnapshot!.documents {
// ...
let post = Post()
posts.append(post)
}
completion(posts)
}
}
}
Второй вариант заключается в том, что у меня есть функция для получения одного сообщения:
static func getPost(listingID: String, completion: @escaping ((_ data: Post) -> Void)) {
db.collection("posts").document(postID).getDocument { (doc, err) in
if let err = err {
print(err)
} else {
if let doc = doc, doc.exists {
if let data = doc.data() {
// ...
let post = Post()
completion(post)
}
}
}
}
}
а затем, чтобы получить все понравившиеся сообщения, я использую следующую функцию:
static func getLikedPosts(likedIDs: [String], completion: @escaping ((_ data: [Post]) -> Void)) {
var posts = [Post]()
for id in likedIDs {
getPost(postID: id) { (post) in
listings.append(post)
if posts.count == likedIDs.count {
completion(posts)
}
}
}
}
Мой вопрос в том, какой из этих двух вариантов более эффективен / масштабируем для большого количества сообщений или есть лучший вариант? Я бы предположил, что использование поля where будет более сложным по времени, но не уверен в том, как firebase управляет этими запросами.
Ответ №1:
Между этими двумя подходами не будет существенной разницы в производительности. Я лично предпочитаю получать каждое сообщение по его идентификатору, так как это означает, что мне не нужно иметь дело с ограничением в 10 значений для in
запроса. Но, как уже было сказано: это только личное предпочтение.
Единственным лучшим вариантом было бы, если бы вы могли получить избранное для пользователя с помощью запроса равенства ( ==
) или запроса диапазона ( >
, <
, >=
, <=
), но я не видел для этого варианта использования.
Другой альтернативой является сохранение избранных сообщений пользователя в отдельной (вспомогательной) коллекции для этого пользователя, чтобы затем вы могли просто прочитать всю эту коллекцию. Это означает, что вы будете дублировать записи при их записи и поддерживать их в соответствии с данными при их обновлении, но взамен вы получите более быстрое и масштабируемое поведение чтения.
Это обычный компромисс при использовании баз данных NoSQL: и является реализацией классического компромисса между пространством и временем.