#javascript #firebase #google-cloud-firestore #google-cloud-functions
# #javascript #firebase #google-cloud-firestore #google-cloud-функции
Вопрос:
ПРОБЛЕМА
Примечание: запрос задается с помощью этого блока кода:
let query = this.firestore
.collection("films")
.doc(filmId)
.collection("casting")
.orderBy("name", "desc"); // <---- DESC. ORDER
if (startAfter) { <---- // TO AVOID STARTING AFTER NULL DOCS (which are at the bottom in descending order)
console.log(JSON.stringify(startAfter, null, 2)); // IN THE SECOND CALL TO THE FUNCTION, THIS SHOWS THE REFERENCE TO THE LAST RETRIEVED DOCUMENT (in the previous call)
query = query.startAfter(startAfter);
}
У меня есть облачная функция firebase, которая извлекает данные (актеров) из коллекции фильмов. Для разбивки на страницы я использую ссылку на документ, например:
return query
.limit(size)
.get()
.then((querySnapshot) => {
const actorsNames = querySnapshot.docs.map((doc) => doc.name);
// Update the offset
startAfter = querySnapshot.docs[querySnapshot.docs.length - 1]; // <---- THIS
return { actorsNames, startAfter };
});
Как вы можете видеть, каждый раз, когда я извлекаю N (= 5) документов, я получаю ссылку на последний документ и обновляю смещение для разбивки на страницы. Затем я отправляю его обратно (обновленное смещение) клиенту, который вызовет функцию вызова firebase с этим новым смещением в качестве данных, если он захочет получить другое количество участников.
Чтобы избежать запуска после null в порядке desc, я условно задаю запрос следующим образом:
let query = this.firestore
.collection("films")
.doc(filmId)
.collection("casting")
.orderBy("name", "desc"); // <---- DESC. ORDER
if (startAfter) { <---- // TO AVOID STARTING AFTER NULL DOCS (which are at the bottom in descending order)
console.log(JSON.stringify(startAfter, null, 2)); // IN THE SECOND CALL TO THE FUNCTION, THIS SHOWS THE REFERENCE TO THE LAST RETRIEVED DOCUMENT (in the previous call)
query = query.startAfter(startAfter);
}
Проблема, с которой я сталкиваюсь, заключается в том, что во второй выборке startAfter имеет правильное значение, последний документ, полученный из pevious вызова, но по какой-то причине запрос извлекает те же документы, что и первый.
Результат
Первый вызов (startAfter = null):
-Resulted documents: [Tom Holland, Quentin Tarantino, Margot Robbie, Leonardo DiCaprio, Emma Watson] (EXPECTED RESULTS)
Второй вызов (startAfter = ссылка на документ Эммы Уотон)
-Resulted documents: [Tom Holland, Quentin Tarantino, Margot Robbie, Leonardo DiCaprio, Emma Watson] (AGAIN, THE SAME RESULTS)
Я понятия не имею, почему это работает не так, как ожидалось. В документации пример разбивки на страницы с помощью ссылки на документ действительно похож (но без OrderBy desc ).
https://firebase.google.com/docs/firestore/query-data/query-cursors#paginate_a_query
Редактировать
В обоих случаях я выполняю одни и те же запросы.
-> Для первой выборки на клиенте я делаю:
// (Ignoring error catching for simplity)
const response = await firebase.functions
.httpsCallable("getActors")({ startAfter: startAfter.current}) // Currently, startAfter.current is null
// Update the startAfter cursor
startAfter.current = response.data.startAfter;
Затем в облачной функции firebase я выполняю запрос, описанный выше, и он возвращает эти данные [Том Холланд, Квентин Тарантино, Марго Робби, Леонардо Ди Каприо, Эмма Уотсон] и, очевидно, обновленное смещение startAfter .
-> Для второй выборки я делаю то же самое:
// (Ignoring error catching for simplity)
const response = await firebase.functions
.httpsCallable("getActors")({ startAfter: startAfter.current}) // But here, startAfter is a reference to the emma watson's document
// Update the startAfter cursor
startAfter.current = response.data.startAfter;
Но по некоторым причинам он возвращает мне те же данные (то же смещение), что и предыдущий вызов.
Обновить
Я выполняю те же запросы на стороне клиента (без облачных функций), и все работает хорошо. Похоже, что облачная функция не возвращает DocumentSnapshot из-за сериализации данных. Есть идеи?
Комментарии:
1. Что
query
в вашем первом запросе? Пожалуйста, отредактируйте вопрос, чтобы было ясно, что именно вы запрашиваете в обоих случаях. Кроме того, я предлагаю не использовать JSON.stringify для регистрации произвольных объектов. Объекты DocumentSnapshot имеют API, который предоставит вам информацию, которую вы можете зарегистрировать.2. Запрос одинаков в обоих вызовах, но в первом вызове startAfter имеет значение null . Я отредактирую это, чтобы было более понятно.
Ответ №1:
Запросы были хорошими! Проблема заключалась в том, что моя облачная функция сериализовала DocumentSnapshot (поскольку это сложный объект), прежде чем возвращать его клиенту.
Я решил эту проблему, установив uuid для каждого документа, а затем используя его в качестве курсора для своих запросов вместо самого снимка документа.
Ответ №2:
Мы здесь многого не видим (как вы перешли от actorID к документам actor?), Но я отмечу, что результаты, которые вы показываете, не упорядочены по имени….
Комментарии:
1. Это упрощенный пример того, что я получаю в своем реальном сценарии, я забыл заказать вывод (обновленный), извините. Но код тот же. Кроме того, я не собираюсь переходить от actorID к документам actor в этом запросе (я имею в виду, я касаюсь только одной вложенной коллекции). В моей подборке приведений у меня есть документы с именами действующих лиц (и другими данными) в качестве полей. Каждый документ представляет субъекта.