8

Is there a way to retrieve the updated value of a document field updated using firestore.FieldValue.increment without asking for the document?

var countersRef = db.collection('system').doc('counters');

await countersRef.update({
    nextOrderCode: firebase.firestore.FieldValue.increment(1)
});

// Get the updated nextOrderCode without asking for the document data?

This is not cost related, but for reliability. For example if I want to create a code that increases for each order, there is no guaranty that if >= 2 orders happen at the same time, will have different codes if I read the incremental value right after the doc update resolves, because if >= 2 writes happen before the first read, then at least 2 docs will have the same code even if the nextOrderCode will have proper advance increment.

Christos Lytras
  • 36,310
  • 4
  • 80
  • 113

3 Answers3

6

Update

Possible now, check other answer.


It's not possible. You will have to read the document after the update if you want to know the value.

If you need to control the value of the number to prevent it from being invalid, you will have to use a transaction instead to make sure that the increment will not write an invalid value. FieldValue.increment() would not be a good choice for this case.

Jemshit
  • 9,501
  • 5
  • 69
  • 106
Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
3

We can do it by using Firestore Transactions, like incremental worked before Field.increment feature:

try {
  const orderCodesRef = admin.firestore().doc('system/counters/order/codes');
  let orderCode = null;
  await admin.firestore().runTransaction(async transaction => {
    const orderCodesDoc = await transaction.get(orderCodesRef);
    if(!orderCodesDoc.exists) {
      throw { reason: 'no-order-codes-doc' };
    }

    let { next } = orderCodesDoc.data();
    orderCode = next++;
    transaction.update(orderCodesRef, { next });
  });

  if(orderCode !== null) {
    newOrder.code = orderCode;
    const orderRef = await admin.firestore().collection('orders').add(newOrder);

    return success({ orderId: orderRef.id });
  } else {
    return fail('no-order-code-result');
  }
} catch(error) {
  console.error('commitOrder::ERROR', error);
  throw errors.CantWriteDatabase({ error });
}
Christos Lytras
  • 36,310
  • 4
  • 80
  • 113
1

Had the same question and looks like Firestore Python client doc_ref.update() returns WriteResult that has transform_results attribute with the updated field value

syldman
  • 505
  • 1
  • 6
  • 18