Firestore: как я могу использовать транзакцию для чтения, а затем записи в документ, на который у меня нет ссылки? - PullRequest
0 голосов
/ 01 августа 2020

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

var myPromise = db.collection("games").where("started", "==", false).orderBy("created").limit(1).get()

Мне нужно создать транзакцию, в которой выполняется чтение из этого документа, а затем запись. Например (взято из документации):

// Create a reference to the SF doc.
var sfDocRef = db.collection("cities").doc("SF");

// Uncomment to initialize the doc.
// sfDocRef.set({ population: 0 });

return db.runTransaction(function(transaction) {
    // This code may get re-run multiple times if there are conflicts.
    return transaction.get(sfDocRef).then(function(sfDoc) {
        if (!sfDoc.exists) {
            throw "Document does not exist!";
        }

        // Add one person to the city population.
        // Note: this could be done without a transaction
        //       by updating the population using FieldValue.increment()
        var newPopulation = sfDoc.data().population + 1;
        transaction.update(sfDocRef, { population: newPopulation });
    });
}).then(function() {
    console.log("Transaction successfully committed!");
}).catch(function(error) {
    console.log("Transaction failed: ", error);
});

Я хочу заменить переменную sfDocRef на переменную myPromise, но не могу, поскольку одна ссылка на документ, а другая - обещание. Как я могу создать транзакцию для документа, который представляет myPromise?

Ответы [ 2 ]

1 голос
/ 02 августа 2020

Вам нужно дождаться разрешения обещания, например, добавив обратный вызов then:

myPromise.then((querySnapshot) => {
  let ref = querySnapshot.documents[0].ref;
  return db.runTransaction(function(transaction) {
    return transaction.get(ref).then(function(sfDoc) {
        if (!sfDoc.exists) {
            throw "Document does not exist!";
        }
        var newPopulation = sfDoc.data().population + 1;
        transaction.update(sfDocRef, { population: newPopulation });
    });
  }).then(function() {
    console.log("Transaction successfully committed!");
  }).catch(function(error) {
    console.log("Transaction failed: ", error);
  });
});

Этот querySnapshot.documents[0].ref предполагает, что существует только один совпадающий документ или что вас интересует только первый документ. Если вас интересует больше, вам нужно oop поверх документов в моментальном снимке запроса.

Вам все равно понадобится get указанный c документ внутри транзакции , если (и только если) вы хотите, чтобы транзакция гарантировала, что этот документ не был изменен между запросом и когда вы записываете его в транзакцию. Если в этом нет необходимости, вы можете использовать QueryDocumentSnapshot из QuerySnapshot.

1 голос
/ 02 августа 2020

После того, как вы действительно выполните этот запрос, ссылка станет легко доступной. Вы можете просто:

  1. Выполнить запрос, как вы сейчас
  2. Найти DocumentSnapshot в результатах запроса (как обычно при обработке результатов запроса)
  3. Используйте свойство ref DocumentSnapshot, чтобы получить ссылку на документ, которая является DocumentReference
  4. Используйте эту ссылку в транзакции.
...