Разбиение на страницы со значением поля, которое происходит несколько раз, возвращает одни и те же документы каждый раз, когда firestore

#node.js #react-native #google-cloud-firestore #pagination #nosql

#node.js #react-native #google-облако-firestore #разбивка на страницы #nosql

Вопрос:

У меня есть запрос на комментарии с полем OrderBy в threadCommentCount. У многих комментариев будет threadCommentCount, равный 0, поэтому каждый раз, когда я передаю последний комментарий threadCommentCount в другой запрос со значением startAfter, равным 0, он каждый раз возвращает один и тот же набор данных. Как бы мне это исправить? Могу ли я добавить еще один startAfter или OrderBy после первого, чтобы упорядочить по времени или что-то в этом роде? Вот функция cloud, которую я использую. Это происходит только тогда, когда значение запроса OrderBy является «популярным», последние отлично работают.

 const postId = req.query.postId;
    const userHandle = req.user.userHandle;
    const orderBy = req.query.orderBy;
    const startAfter = req.query.startAfter;

    db
        .collection('posts')
        .doc(postId)
        .get()
        .then(async (doc) => {
            if(!doc.exists){
                throw 'postNotFound';
            }
            else {
                    let popularCommentsQuery;
                    popularCommentsQuery = db
                        .collection('comments')
                        .where('postId', '==', postId)
                        .orderBy('threadCommentCount', 'desc')
                        .startAfter(startAfter)
                        .limit(15) // this is the query that I'm having problems with
                    const popularComments = await popularCommentsQuery.get();
                    return popularComments;
            }
        })
        .then((data) => {
            const promises = data.map((doc) => {
                return {
                    userHandle: doc.data().userHandle,
                    comment: doc.data().comment,
                    commentId: doc.id,
                    postId: doc.data().postId,
                    threadCommentCount: doc.data().threadCommentCount,
                    commentedAt: doc.data().commentedAt
                };
            });
            Promise.all(promises)
            .then((comments) => {
                return res.json(comments);
            });
        })
        .catch((err) => {
          console.error(err);
          return res.json({error: `Could not get comments on post ID ${postId}`});
        });
  

во внешнем интерфейсе я устанавливаю количество комментариев потока равным 0, поэтому запрос начинается снова с 0, следовательно, он получает те же данные. Поля, которые, как я знаю, должны отличаться, — это commentId (идентификатор документа) или время, опубликованное на данный момент. Любая помощь приветствуется!

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

1. Я не совсем понимаю, о чем вы спрашиваете. Приведенный здесь код показывает много запросов, а не только один, поэтому трудно сказать, что вы имеете в виду. Пожалуйста, сократите этот пример до одного запроса и опишите конкретное поведение этого одного запроса, который работает не так, как вы хотите.

2. Хорошо, я все обрезал и добавил комментарий в коде точного запроса, который вызывает у меня проблемы. Извините

Ответ №1:

Вы можете передать последний снимок документа предыдущей страницы в пункт cursor следующей страницы в качестве отправной точки.

В вашей облачной функции вместо startAfter значения threadCommentCount вы можете передать docId последнего документа, а затем получить его снимок документа для передачи .startAfter() методу.

Вот пример этого в документах

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

1. Спасибо за ваш ответ! В моей голове возникла идея, которой раньше не было, лол. Я просто передам идентификатор комментария на серверную часть и получу снимок оттуда. Работает отлично. Спасибо!

2. @Jose V, Но это добавит дополнительное количество прочитанных, просто чтобы получить снимок для целей запроса. Есть ли лучший способ, чем этот?