防止在对象集包含时覆盖 Cloud Function 中的 createdAt 和 updatedAt

Posted

技术标签:

【中文标题】防止在对象集包含时覆盖 Cloud Function 中的 createdAt 和 updatedAt【英文标题】:Prevent overwriting createdAt and updatedAt in Cloud Function when object set includes them 【发布时间】:2020-08-23 09:46:21 【问题描述】:

我正在编写一些 Node.js 代码,以将现有数据库中的数据导入 Firebase Cloud Firestore。我们已经创建了我希望在过渡中保留的日期和更新日期。问题是我们创建了 Cloud Functions 来自动设置对象创建时的设置,因此它总是用当前时间戳覆盖对象的值。如果我再次运行我们的导入脚本,因此 set 正在更新现有文档,则保留对象中的 createdAt 和 updatedAt 值。

我怎样才能让它使用指定的值而不用创建时的当前时间戳覆盖它们?

const oldNote = 
  id: "someid",
  text: "sometext",
  createdAt: new Date(2018, 11, 24, 10, 33, 30, 0),
  updatedAt: new Date(2018, 11, 24, 10, 33, 30, 0)


const note = 
  text: oldNote.text,
  createdAt: firebase.firestore.Timestamp.fromDate(oldNote.createdAt),
  updatedAt: firebase.firestore.Timestamp.fromDate(oldNote.updatedAt)
;
firestoredb.collection("notes").doc(oldNote.id).set(note).then((docRef) => 
    //FIXME: createdAt and updatedAt aren't preserved, always today
).catch((error) => 
    console.error("Error setting user: ", error);
);

这里是云函数:

exports.updateCreatedAt = functions.firestore
.document("collectionName/id")
.onCreate((snap, context) => 
    const now = admin.firestore.FieldValue.serverTimestamp();

    return snap.ref.set(
        
            createdAt: now,
            updatedAt: now
        ,
         merge: true 
    );
);

exports.updateUpdatedAt = functions.firestore
.document("collectionName/id")
.onUpdate((change, context) => 
    const newValue = change.after.data();
    const previousValue = change.before.data();

    if (
        Boolean(newValue.updatedAt) &&
        Boolean(previousValue.updatedAt) &&
        newValue.updatedAt.isEqual(previousValue.updatedAt)
    ) 
        const now = admin.firestore.FieldValue.serverTimestamp();

        return change.after.ref.set( updatedAt: now ,  merge: true );
     else 
        return false;
    
);

【问题讨论】:

dateobj 到底是什么?请不遗余力。我们应该能够获取您的代码并自己运行它。 @DougStevenson 这是一个 javascript 日期对象。这只是一个例子,旧笔记是从不同的数据库中查询的。 确切的值很重要。 【参考方案1】:

我继续在 Google Cloud Console 中部署了对 onCreate 触发器的更新。它现在检查对象是否已经包含 createdAt 和/或 updatedAt 并使用它们而不是覆盖它们。

exports.updateCreatedAt = functions.firestore
.document("collectionName/id")
.onCreate((snap, context) => 
    const now = admin.firestore.FieldValue.serverTimestamp();
    const createdAt = snap.data().createdAt != undefined ? snap.data().createdAt : now;
    const updatedAt = snap.data().updatedAt != undefined ? snap.data().updatedAt : now;

    return snap.ref.set(
        
            createdAt: createdAt,
            updatedAt: updatedAt
        ,
         merge: true 
    );
);

【讨论】:

【参考方案2】:

正如您从Timestamp.fromDate() 的 API 文档中看到的那样,采用 Date 对象并将其转换为 Timestamp 对象。但是,您将向它传递一个 Timestamp 对象(除非您的编辑是伪造的值不是来自 Cloud Functions 中写入的数据库)。这是不必要的转换,它可能只是返回当前时间而不是您期望的时间。只需使用适当的时间戳值:

const note = 
  text: oldNote.text,
  createdAt: oldNote.createdAt,
  updatedAt: oldNote.updatedAt
;

请记住,当您将日期写入 Firestore 时,它​​会在内部存储一个时间戳。它不会以日期的形式出现。

【讨论】:

oldNote 的 created/updatedAt 是 JavaScript 日期对象,而不是 firebase.firestore.Timestamp。 嗯,你在云函数中写的内容将存储一个时间戳。 这是所希望的。新笔记应该有时间戳。 是的,所以,正如我在这里所说,如果您使用 oldNote 从文档中提取时间戳,则无需转换。 文档以与我在这里相同的方式显示它:dateExample: admin.firestore.Timestamp.fromDate(new Date('December 10, 1815')),

以上是关于防止在对象集包含时覆盖 Cloud Function 中的 createdAt 和 updatedAt的主要内容,如果未能解决你的问题,请参考以下文章

如何防止覆盖其他人修改过的对象

Google Cloud Vision - 数据集不能拆分为训练、验证、测试数据

我可以防止 RestKit+CoreData 覆盖本地实体更改吗?

xcodebuild:在使用条件集错误覆盖参数时实现对宏的 XCBuild 支持

Prisma 和 ApolloClient:防止前端覆盖关系的后端包含条件

加载多个数据集而不覆盖变量