【问题标题】:How can I decrement a field value from firestore after submitting a form successfully?成功提交表单后,如何从 firestore 中减少字段值?
【发布时间】:2021-09-08 05:20:59
【问题描述】:

我从 firestore 收集了这些物品:

  • 可用性:真
  • 库存:100
  • 项目:项目1

我有点想在提交表单后减少库存:我有这些where() 来比较用户选择的是否与保存在 firestore 中的相同。

  function incrementCounter(collref) {
    collref = firestore
      .collection("items")
      .doc()
      .where(selectedItem, "==", selectedItem);

    collref.update({
      stocks: firestore.FieldValue.increment(-1),
    });
  }

这就是我提交表单的方式,我在保存后设置了incrementCounter()

 const handleSubmit = (e) => {
    e.preventDefault();
    try {
      const userRef = firestore.collection("users").doc(id);
      const ref = userRef.set(
        {
         ....
          },
        },

        { merge: true }
      );

      console.log(" saved");
      incrementCounter();
    } catch (err) {
      console.log(err);
    }
  };

提交表单没有错误。但是,incrementCounter() 不起作用并显示此错误:

TypeError: _Firebase_utils__WEBPACK_IMPORTED_MODULE_5__.firestore.collection(...).doc(...).where is not a function

【问题讨论】:

  • 我相信您使用的 FieldValue 错误。如果您的 firestore 变量类似于 const firestore = firebase.firestore(),那么您不能在更新部分的 FieldValue 中使用 firestore。您将不得不使用stocks: firebase.firestore.FieldValue.increment(-1)
  • @SulmanAzhar 我仍然遇到同样的错误
  • 还要确认.where(selectedItem, "==", selectedItem) 是否为有效语句。例如,它正在检查字段 itemName 的值 itemName。也许分享您文档的屏幕截图,以便我们确认您是否需要。
  • @Dharmaraj 我添加了文档的屏幕截图。谢谢
  • @Jenn 这似乎是另一个问题。如果您尝试减少项目为item1 的文档字段,则将其更改为:.where("item", "==", selectedItem) 除此之外,我的回答中还提到了其他问题

标签: javascript reactjs firebase google-cloud-firestore


【解决方案1】:

这里的问题很少

  1. 这两个函数都应该有异步等待
  2. 您的 fieldValue 应该从 firebase.firestore.FieldValue not firestoreFieldValue 开始
  3. where 子句也用于收集,而不是 doc(),因此也将其删除。此外,我认为这不会更新完整的集合,但请检查并查看。 (你得到的错误是因为这个)

我不知道你是如何在这个应用程序中导入 firebase 的,我不知道你是如何声明 firestore 但大多数 firestore 变量是这样声明的

const firestore = firebase.firestore();

在这里,firestore 是一个函数,而不是一个属性 但是当您在FieldValue 中使用它时,它应该是这样的

firebase.firestore.FieldValue.increment(-1),

注意这里的firestore是一个属性而不是一个函数

你的完整代码应该是这样的

async function incrementCounter(collref) {
    collref = firestore
      .collection("items")
      .where(selectedItem, "==", selectedItem);

    const newRef = await collref.get();
    for(let i in newRef.docs){
      const doc = newRef.docs[i];
      await doc.update({
       stocks: firebase.firestore.FieldValue.increment(-1),
     }); 
       // You can also batch this 
    }
  }



const handleSubmit = async (e) => {
    e.preventDefault();
    try {
      const userRef = firestore.collection("users").doc(id);
      const ref = await userRef.set(
        {
         ....
          },
        },

        { merge: true }
      );

      console.log(" saved");
      await incrementCounter();
    } catch (err) {
      console.log(err);
    }
  };

【讨论】:

【解决方案2】:

where() 方法存在于CollectionReference 而不是DocumentReference。您还需要首先获取对这些文档的引用,因此首先获取所有匹配的文档,然后使用Promise.all()Batch Writes 更新所有文档:

function incrementCounter() {
  // not param required  ^^
  const collref = firestore
      .collection("items")
      // .doc() <-- remove this
      .where(selectedItem, "==", selectedItem);
      //      ^^^                 ^^^
      //      doc field           field value
      //      "item"              {selectedItemName}

  collRef.get().then(async (qSnap) => {
    const updates = []
    qSnap.docs.forEach((doc) => {
      updates.push(doc.ref.update({ stocks: firebase.firestore.FieldValue.increment(-1) }))
    })
    await Promise.all(updates)
  })
}

如果您更新的文档少于 500 个,请考虑使用批量写入来确保所有更新要么失败要么通过:

collRef.get().then(async (qSnap) => {
  const batch = firestore.batch()

  qSnap.docs.forEach((doc) => {
    batch.update(doc.ref, { stocks: firebase.firestore.FieldValue.increment(-1) })
  })

  await batch.commit()
})

您可以在documentation 中阅读有关批量写入的更多信息

【讨论】:

  • 谢谢。它确实有效,我也使用了批处理的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多