Функции Firebase — Как вернуть снимок документа из облачной функции?

#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 в этом запросе (я имею в виду, я касаюсь только одной вложенной коллекции). В моей подборке приведений у меня есть документы с именами действующих лиц (и другими данными) в качестве полей. Каждый документ представляет субъекта.