Как вернуть родительскую коллекцию на основе значения документа вложенной коллекции в Firestore?

#javascript #firebase #google-cloud-firestore

#javascript #firebase #google-cloud-firestore

Вопрос:

У меня есть эта коллекция в моем Firestore:

 Collection: Team1
  Document: TeamName
    Subcollection: Notes
    Subcollection: Users    
       Document: user1 => Field: name: "Anna", uid: "someID"
       Document: user2 => Field: name: "John", uid: "someID"
  

Давайте представим сценарий, в котором существует много коллекций команд с приведенной выше схемой. Как вернуть всю коллекцию Team с помощью JavaScript (чтобы я мог получить доступ, например, к заметкам) на основе поля Name в Document (в вложенной коллекции Users).

Я попробовал это:

  var nameRef = db
    .collection('Team1')
    .doc('TeamName')
    .collection('Users')
    .where('name', '==', 'Anna')

const getData => ()=> {
  nameRef.get().then((snapshot) => {
      snapshot.docs.forEach((doc) => {
        console.log(doc.data())
      })
    })
}

  

Однако приведенный выше код выводит только поля документа в пользовательском документе (имя, uid).

Ответ №1:

Ваш запрос вернет только документы из Users коллекции. Если вы также хотите отображать данные от пользователя, вам нужно будет загрузить их документ отдельно. Для TeamName пользователя это было бы:

 db
  .collection('Team1')
  .doc('TeamName')
  .get()
  

Или, в качестве альтернативы, вы можете определить и получить родительский документ для пользователя с помощью:

 doc.ref.parent.parent.get()
  

Если вы хотите выполнить поиск пользователей с именем Anna во всех командах, вы можете использовать запрос группы сбора. Это особый тип запроса, который выполняет поиск по всем коллекциям с определенным именем.

 var nameRef = db
    .collectionGroup('Users')
    .where('name', '==', 'Anna')

const getData => ()=> {
  nameRef.get().then((snapshot) => {
      snapshot.docs.forEach((doc) => {
        console.log(doc.data())
      })
    })
}
  

Здесь опять же, это загружает только пользователей, а не их команды. Но вы можете использовать тот же doc.ref.parent.parent.get() фрагмент, что и раньше, чтобы затем также находить и загружать командный документ для каждого пользователя.

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

1. Спасибо, еще одна вещь. Когда я возвращаю doc.ref.parent.parent.get() Я получаю обещание:__proto__: Promise [[PromiseState]]: «выполнено» [[PromiseResult]]: t Df: e {lf: n, f: e, ff: FirebaseAppImpl, df: e, INTERNAL: {…}, …} E : t {путь: n} I_: null Mf: false Of: false kf: n {ключ: t, версия: t, nn: t, Ye: false, hasCommittedMutations: false} существует: (…) идентификатор: (…) метаданные: (…) ссылка: (…) прото : ОбъектПод E_ находятся родители. Как сохранить массив в переменную? Я попробовал реструктуризацию объекта, но это не сработало.

2. Да, как и в случае с вашим исходным get() кодом, вам нужно будет добавить еще .then() одну с функцией для обработки результирующего снимка. В рамках этой функции вы могли бы использовать snapshot.docs.forEach цикл для переноса данных из каждого документа в заранее определенный массив.

Ответ №2:

В дополнение к .data() методу, полученное doc также имеет .parent свойство, которое содержит CollectionReference — в этом случае оно будет ссылаться на вашу Users коллекцию. У этой коллекции также есть .parent свойство, которое будет указывать на ваш TeamName документ. Его родительский элемент будет указывать на вашу Team1 коллекцию.

Используя эти родительские свойства документов и коллекций, вы можете проложить свой путь «вверх» по дереву до своей коллекции Team, из которой вы можете извлекать ее документы.