#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, что мне все еще интересно, правильно ли я это делаю (см. отредактированный вопрос)