Получение более старого снимка для разбивки на страницы при запросе с помощью limit (toLast:)

#ios #swift #firebase #google-cloud-firestore

#iOS #быстрый #firebase #google-облако-firestore #swift

Вопрос:

Я создаю функцию чата для своего приложения с помощью Firestore. Я использую limit(toLast:) поскольку я извлекаю данные на основе метки времени, этот метод выдает мне последние сообщения, сохраненные в моей базе данных. Но это доставляет мне проблемы при попытке получить снимок / документы до этого для загрузки старых сообщений. Вот мой код:

 fileprivate func paginateFetchMessages() {
    var query: Query!
    
    if let nextStartingSnap = self.lastDocumentSnapshot {
        query = DBCall.fireRef.collection("friendMessages")
        .document(currentUID)
        .collection(friendUID)
        .order(by: "timestamp").limit(toLast: 5).start(afterDocument: nextStartingSnap)
    } else {
        query = DBCall.fireRef.collection("friendMessages")
        .document(currentUID)
        .collection(friendUID)
        .order(by: "timestamp").limit(toLast: 5)
    }
    
    query.addSnapshotListener { querySnapshot, error in
        guard let snapshot = querySnapshot else {
            print("Error fetching snapshots: (error!)")
            return
        }
        
        guard let lastSnap = snapshot.documents.last else {
            self.refreshControl.endRefreshing()
            return
        }
        
        print(snapshot.documents)
        
        self.lastDocumentSnapshot = lastSnap
        
        snapshot.documentChanges.forEach({ (change) in
            
            if change.type == .added {
               let data = change.document.data()
                let text = data["message"] as! String
                let fromID = data["fromID"] as! String
                let messageID = data["messageId"] as? String ?? ""
                let isRead = data["isRead"] as? Bool ?? false
                let timestamp = data["timestamp"] as! Timestamp
                
                let user = MessageKitUser(senderId: fromID, displayName: "")
                let message = MessageKitText(text: text, user: user, messageId: messageID, date: Date(), isRead: isRead, firDate: timestamp )
                
                self.insertMessage(message)
                self.refreshControl.endRefreshing()
            }
        })
    }
}
  

Когда я использую snapshot.documents.last , ничего не возвращается, потому что я изначально выбираю «последние» документы. Мне нужно получать 5 снимков до последнего, каждый раз при разбивке на страницы.

Дайте мне знать, если это не имеет смысла и у вас есть вопросы. Спасибо!!

Ответ №1:

Допустим, у вас есть 10 документов:

 [1,2,3,4,5,6,7,8,9,10]
  

Ваш limitToLast(5) получит:

 [6,7,8,9,10]
  

Поскольку вы используете start(afterDocument: , Firestore запускается после document 6 , а это не то, что вы хотите. Вместо этого вы хотите, чтобы end(beforeDocument: :

 query = DBCall.fireRef.collection("friendMessages")
.document(currentUID)
.collection(friendUID)
.order(by: "timestamp")
.end(beforeDocument: nextStartingSnap)
.limit(toLast: 5)
  

Я также переворачиваю limit(toLast: и end(beforeDocument: . Это не влияет на результаты, но для меня читается немного проще — поскольку Firestore в значительной степени обрабатывает ваш запрос:

  • Он загружает индекс на timestamp .
  • Это отключило все, начиная с nextStartingSnap этого момента.
  • Затем он возвращает последние 5 документов, которые остаются в результате.

Комментарии:

1. Небольшое предупреждение: end (до того, как документу потребуется обратный индекс — в сообщении об ошибке будет указана ссылка для его создания

2. Большое вам спасибо @Frank, это то, что мне было нужно. Все, что мне нужно было сделать дальше, это изменить snapshot.documents.last на snapshot.documents.first , и я получил правильный результат.

3. Хороший момент. Прокрутка назад по-прежнему сбивает меня с толку большую часть времени, но это не вина API. 🙂