如何使用 Ionic 4 删除 Firebase Cloud Firestore 中的元素数组

How to Remove Arrays of Element in Firebase Cloud Firestore using Ionic 4

In My Cloud Firestore 数据库结构如下所示。现在,我想像这样删除基于 Index 0Index 1 的索引位置。

const arrayLikedImagesRef = {imageurl: image, isliked: true};
  const db = firebase.firestore();
  const deleteRef = db.collection('userdata').doc(`${phno}`);
  deleteRef.update({
    likedimages: firebase.firestore.FieldValue.arrayRemove(arrayLikedImagesRef)
  });
});

因为explained here, “bad things can happen when trying to update or delete array elements at specific indexes”. This is why the Firestore official documentation表示arrayRemove()函数将元素(字符串)作为参数,而不是索引。

中所建议,如果您更喜欢使用索引,那么您应该获取整个文档、获取数组、修改它并将其添加回数据库。

您不能使用 FieldValue 按索引删除数组项。相反,您可以使用 transaction 来删除数组项。使用事务可确保您实际上写回了您期望的确切数组,并且可以与其他编写器打交道。

例如(我这里引用的是任意的,当然需要你提供正确的引用):

db.runTransaction(t => {
  const ref = db.collection('arrayremove').doc('targetdoc');

  return t.get(ref).then(doc => {
    const arraydata = doc.data().likedimages;

    // It is at this point that you need to decide which index
    // to remove -- to ensure you get the right item.
    const removeThisIndex = 2;

    arraydata.splice(removeThisIndex, 1);
    t.update(ref, {likedimages: arraydata});
  });
});

当然,正如上面代码中所指出的,只有当您实际上在事务本身内部时,您才能确定要删除正确的索引——否则您获取的数组可能与数组不对齐您最初选择索引的数据。所以要小心!


就是说,鉴于 FieldValue.arrayRemove 不支持嵌套数组(因此您无法将多个映射传递给它以进行删除),您可能会问该怎么做。在那种情况下,您只需要上面的变体来实际检查值(此示例仅适用于单个值和固定对象类型,但您可以轻松地将其修改为更通用):

const db = firebase.firestore();
const imageToRemove = {isliked: true, imageurl: "url1"};

db.runTransaction(t => {
  const ref = db.collection('arrayremove').doc('byvaluedoc');
  return t.get(ref).then(doc => {
    const arraydata = doc.data().likedimages;
    const outputArray = []
    arraydata.forEach(item => {
      if (!(item.isliked == imageToRemove.isliked &&
            item.imageurl == imageToRemove.imageurl)) {
           outputArray.push(item);
          }
    });
    t.update(ref, {likedimages: outputArray});
  });
});

(我确实注意到,在您的代码中,您使用的是原始布尔值,但数据库将 isliked 项目作为字符串。我测试了上面的代码,尽管如此,它似乎仍然有效,但它'最好在类型的使用上保持一致)。