Firestore批量合并

时间:2020-08-03 21:21:37

标签: 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()

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

{
    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 } ]
  }

但是,当文档提交到Firestore时,只会显示以下结构(标签和类别数组均为空) enter image description here

据我了解,merge应该对所有嵌套对象进行深度合并。如果不是这种情况,我该如何实现自己的追求?

我知道这种类型的存储不能扩展成千上万的标签,我只是第一次修改firestore,想看看我将如何使这种东西工作

1 个答案:

答案 0 :(得分:3)

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

最重要的是,Firestore完全不支持设置嵌入在数组中的特定映射字段值。换句话说,没有使用数组索引的直接数组项更新。

如果必须具有此文档结构,则需要进行事务处理才能读取文档,修改内存中的数组字段以显示所需的格式,然后将该字段写回到文档中。是的,这很不方便,但这是涉及数组项更新的唯一方法。