Firestore批量深度合并

Ale*_*lex 2 typescript google-cloud-firestore

当我从 API 创建新文档时,我想提交(或原子更新)属于根项目文档的统计信息集合:

    const increment = firebase.firestore.FieldValue.increment(1)
    let aggregation: LooseObject = {
      totalProjects: increment,
      tags: [],
      categories: [],
    }

    const project = fakeProject() // some debug func to return a dummy project object
    const projectRef = db.collection('projects').doc()
    const projectStatsRef = db.collection('projects').doc('--stats--')

    project.categories.forEach((category: string) => {
      aggregation.categories[category] = increment
    })

    project.tags.forEach((tag: string) => {
      aggregation.tags[tag] = increment
    })

    console.log(aggregation)

    const batch = db.batch()
    batch.set(projectRef, project)
    batch.set(projectStatsRef, aggregation, {
      merge: true,
    })
    batch.commit()
Run Code Online (Sandbox Code Playgroud)

当我检查控制台时,我得到了聚合文档的以下转储(这是我希望在所附屏幕截图中看到的数据的形状):

{
    totalProjects: NumericIncrementTransform { operand: 1 },
    tags: [
      raid: NumericIncrementTransform { operand: 1 },
      'attack-of-the-clone': NumericIncrementTransform { operand: 1 },
      'star-wars': NumericIncrementTransform { operand: 1 }
    ],
    categories: [ movie: NumericIncrementTransform { operand: 1 } ]
  }
Run Code Online (Sandbox Code Playgroud)

但是,当文档提交到 firestore 时,仅出现以下结构(标签和类别数组均为空) 在此输入图像描述

根据我的理解,merge应该对所有嵌套对象执行深度合并。如果不是这样,我怎样才能实现我所追求的目标?

我知道这种类型的存储无法扩展数千个标签,我只是第一次修改 firestore,想看看如何让这种事情发挥作用

Dou*_*son 5

设置合并并不是真正按照您期望的方式进行“深度”合并。当您传递带有键/值对的对象时,Firestore 将使用新数据完全覆盖每个键指定的字段,但保留文档中的所有其他字段。因此,如果您有一个包含字段 { a, b, c } 的文档,并且对 b 进行了 set-with-merge,则 b 会被完全覆盖,而其他两个则保持不变。

最重要的是,Firestore 根本不支持设置嵌入数组中的特定地图字段值。或者换句话说,不存在使用数组索引的直接数组项更新。

如果您必须具有此文档结构,则需要一个事务来读取文档,修改内存中的数组字段以显示您想要的方式,然后将该字段写回文档。是的,这很不方便,但当涉及数组项更新时,这是唯一的方法。