防止在对象集包含时覆盖 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 支持