Firestore как добавить в вложенную коллекцию

#javascript #firebase #google-cloud-firestore

#javascript #firebase #google-облако-firestore

Вопрос:

Я хотел бы найти документ в коллекции и добавить элементы в вложенную коллекцию (которая, возможно, еще не существует):

 projects (collection)
   project (doc)
      cluster (collection) // might not exist
        node1 (doc)  // might not exist
           statTypeA (collection)  // might not exist
  

Я надеялся на что-то подобное:

 // Know the doc:
db.ref(`projects/${projectId}/cluster/node1/${statType}`).add()
// Or filter and ref:  
db.collection('projects').where(..).limit(1).ref(`cluster/node1/${statType}`).add()
  

В итоге я решил это следующим образом, но это уродливо, многословно и медленно, поскольку сначала он должен вернуться с несколькими операциями чтения. Правильно ли я это делаю?

 const projectRefs = await db.collection('projects')
  .where('licenseKey', '==', licenseKey)
  .limit(1)
  .get();

if (!projectRefs.docs) {
  // handle 404
}

const projectRef = projectRefs.docs[0].ref;

const cluster = await projectRef.collection('cluster')
  .doc('node1').get();

await cluster.ref.collection(statType).add({ something: 'hi' });
  

Редактировать:

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

 // projects
{
  projectId1
}

// instances (to-many-relationship) (filter based on projectId)
{
  projectId
  statTypeA: []
  statTypeB: []
}
  

Ответ №1:

Ваша «неприятная штука» гораздо ближе к тому, как все работает.

В вашей первой попытке вы пытаетесь объединить запрос и создание документа в одной операции. SDK вообще так не работает. Вы либо читаете, либо пишете с любым заданным фрагментом кода, никогда с обоими сразу. Сначала вы должны выполнить запрос, найти документ, а затем использовать его для создания других документов.

get() возвращает обещание, которое вам нужно использовать для ожидания результатов запроса. Результаты доступны не сразу, как в настоящее время предполагается в вашем коде.

В документации показан пример кода, показывающий, как обрабатывать результаты асинхронного запроса. Поскольку ваш код использует async / await, вы можете преобразовать его по мере необходимости. Обратите внимание, что вам нужно повторить QuerySnapshot , полученные из возвращенного обещания, чтобы увидеть, найден ли документ.

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

1. Хм, как ни странно, я вызываю await на get() , я думаю, что, должно быть, я делаю следующий бит неправильно. Возможно, в конечном итоге я просто использую массивы из-за того, что это приводит к увеличению операций чтения / записи и большему усложнению кода и времени ожидания обходов в обоих направлениях в интересах масштабирования, когда коллекции очень большие (маловероятно во многих случаях)

2. Ваш projectRef вообще не является ссылкой. Это DocumentSnapshot, который содержит данные в документе. Возможно, вы хотите получить DocumentReference из этого снимка, используя его свойство ref, и использовать это для создания следующей ссылки. firebase.google.com/docs/reference/js /…

3. Спасибо, я думаю, это может быть то, что мне нужно — попробую позже

4. Я заработал, используя ref, но это кажется таким плохим API, что мне все еще интересно, правильно ли я это делаю (см. отредактированный вопрос)