【问题标题】:How to delete a deeply nested field inside a Firebase Object map如何删除 Firebase 对象映射中的深层嵌套字段
【发布时间】:2020-11-02 22:33:54
【问题描述】:

我有一个名为“CourseList”的 Firebase 对象映射,其中包含嵌套字段。这些嵌套字段本身就是包含更多嵌套字段的对象映射。此外,其中一些对象映射将具有随机生成的名称。

目标是删除随机生成的名称为“352oIP3fdc6IIvuBbajR0”(蓝色下划线)的对象映射。 “CourseList”和“LectureList”的名称是静态名称,但红色的CourseID(随机生成名称“2dfPipFRKiB6TAKab4jv8”)。

通过关注 stackOverflow 上的其他问题,如果我想删除红色对象映射“2dfPipFRKiB6TAKab4jv8”,我能够使删除功能正常工作。

let CID = '2dfPipFRKiB6TAKab4jv8';

await db.collection('users').doc(UID).set( { 
  CourseList : { [CID]: FieldValue.delete() }
    
},{ merge: true }
);

但是,当我尝试删除“352oIP3fdc6IIvuBbajR0”的蓝色下划线子对象映射时,该操作似乎没有执行任何操作,并且 Firebase 文档没有更改。

let CID = "2dfPipFRKiB6TAKab4jv8";
let LID = "352oIP3fdc6IIvuBbajR0";

await db.collection('users').doc(UID).set( { 
  CourseList : { [`${CID}.LectureList.${LID}`]: FieldValue.delete() }

},{ merge: true }
    );

任何关于如何正确删除对象映射内深层嵌套字段的说明将不胜感激。

【问题讨论】:

  • 除了您所期望的之外,这段代码究竟做了什么? “似乎不起作用”是没有足够的信息来处理。还请对值进行硬编码,而不是使用我们看不到值的变量。这里应该有足够的信息,任何人都可以运行代码并看到相同的结果。
  • 当然可以。我将编辑问题以提高读者的清晰度。

标签: javascript firebase google-cloud-firestore


【解决方案1】:

解决方案:

对于未来的读者,这是我用来删除对象映射中高度嵌套的字段的代码。

      const userRec = db.collection('users').doc(UID);
      let userRecData = await userRec.get();
      let userRecResp = {};
      userRecResp = userRecData.data();
      delete userRecResp.CourseList[CID]['LectureList'][LID];  
      await db.collection('users').doc(UID).update(userRecResp); 

请注意,“UID”、“CID”和“LID”是变量名。

【讨论】:

  • 请参阅下面的解决方案,了解一种无需获取对象的简单方法。您的问题几乎到了那里,需要使用 update 而不是 set 与 DOT 路径,firestore 的文档令人困惑
【解决方案2】:

您需要指定嵌套值的完整路径作为传递给set() 的对象的键。你不能像现在这样将它表达为一系列嵌套的对象。

await db.collection('users').doc(UID).set({ 
  [`CourseList.${CID}`]: FieldValue.delete()
},
{ merge: true }
);

【讨论】:

  • 很抱歉造成混乱,但是当我尝试包含完整路径时,它似乎仍然没有删除该字段。 [CourseList.${CID}.LectureList.${LID}]: FieldValue.delete()
  • 你必须使用带有点路径的update 而不是set
【解决方案3】:

虽然帖子很旧,以防以后有人发现

要使 DOT 路径起作用,您必须使用 update 而不是 setset 不处理 DOT 路径,甚至合并。 Merge 将合并所有提供的嵌套对象,因此不会破坏数据。

解决方案:

要使删除工作,您需要调用

let CID = "2dfPipFRKiB6TAKab4jv8";
let LID = "352oIP3fdc6IIvuBbajR0";

await db.collection('users').doc(UID).update( {
 [`CourseList.${CID}.LectureList.${LID}`]: FieldValue.delete() 
} )

如何使用 SET+MERGE 来做同样的事情:

为了与set + merge:true 一起工作,它必须是

let CID = "2dfPipFRKiB6TAKab4jv8";
let LID = "352oIP3fdc6IIvuBbajR0";

await db.collection('users').doc(UID).set({ 
  'CourseList': { 
    [CID]: {
      'LectureList': {
        [LID]: {
          FieldValue.delete() 
        }
      }
    }
  },
  { merge: true }
);

没有理由做set,路由在这里,因为update 是明确的,但它有助于澄清他的操作差异

为什么有一个删除有效:

@andrewB 您的 CID 删除有效,因为没有嵌套路径

以下代码有效,因为它执行了以下操作:

let CID = '2dfPipFRKiB6TAKab4jv8';

await db.collection('users').doc(UID).set( { 
  CourseList : { [CID]: FieldValue.delete() }
},{ merge: true }
);
  1. 尝试将users/${UID 中的键CourseList 替换为{ [CID]: FieldValue.delete() }
  2. 由于merge: true,替换与那里的现有值结合在一起,最终只触及键[CID],而不是粉碎整个对象

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多