
本文探讨了在使用 firestore `array-contains` 查询时可能遇到的一个常见误解,并揭示了异步函数中 `await` 关键字缺失导致批处理操作失效的深层原因。通过分析一个实际案例,我们强调了在处理异步操作,尤其是在 firestore 批处理中,正确使用 `await` 的重要性,以确保数据操作的顺序性和原子性。
在 Firestore 开发中,array-contains 查询是一个强大的工具,用于检索数组字段中包含特定元素的文档。然而,当处理数组中的对象时,开发者经常会遇到一些挑战,尤其是关于对象匹配的精确性。一个常见的误解是,即使对象结构完全一致,array-contains 查询也可能无法按预期工作。本文将深入探讨一个看似与 array-contains 相关,实则由异步批处理操作中的 await 缺失引发的典型问题,并提供解决方案和最佳实践。
在使用 array-contains 查询数组中的对象时,Firestore 要求查询的对象与数组中存储的对象完全一致。这意味着不仅值要相同,对象的键的顺序也必须一致。尽管 Firestore 在存储 Map 类型数据时会自动按键的字母顺序排列,但在某些客户端环境中构建查询对象时,仍需注意确保其结构与数据库中存储的结构保持一致。例如,对于以下用户引用类型:
export type UserReference = {
name?: string;
uid: AppUser['uid'];
};
export const getUserRef = (user: AppUser | DbUser): UserReference => ({
name: user.name,
uid: user.uid,
});即使我们通过 getUserRef 辅助函数确保了对象结构的一致性,有时查询仍然可能不奏效,这可能导致开发者误以为是 array-contains 的问题。
在一个典型的清理场景中,我们可能需要从多个文档中移除某个特定用户的引用。这通常涉及到一个 Firestore 批处理(WriteBatch)操作,以确保所有更新的原子性。考虑以下代码片段,其目的是从所有包含特定用户作为 owners 的群组中移除该用户:
// 假设 user 变量已定义
const linkedGroupQuery = getFirestore()
.collection(constants.dbCollections.groups)
.where('owners', 'array-contains', getUserRef(user)); // 疑似问题点
const querySnapshot = await linkedGroupQuery.get();
querySnapshot.forEach((doc) => {
const linkedGroup = doc.data() as DbGroup;
const owners = linkedGroup.owners.filter((o) => o.uid !== user.uid);
batch.update(doc.ref, { owners });
});
// ... 其他批处理操作
// 假设这里有一个异步辅助函数 severGroupOwnerLinksWithUser
// await severGroupOwnerLinksWithUser(user.uid, batch); // 缺少 await 的情况
// ...
batch.commit();在这个例子中,尽管 array-contains 查询本身可能工作正常,但清理操作却未能完全执行。经过深入排查,发现问题并非出在 array-contains 查询本身,而是由于在一个异步辅助函数调用前缺少了 await 关键字。
当一个异步函数(例如 severGroupOwnerLinksWithUser)在不使用 await 的情况下被调用时,它会立即返回一个 Promise,但其内部的操作会继续在后台执行。如果这个异步函数内部包含了对同一个 WriteBatch 对象的修改,而 batch.commit() 在该异步函数完成之前被调用,那么这些修改将不会被包含在最终提交的批处理中。这会导致部分操作成功,而部分操作失败的令人困惑的局面,因为一些依赖于批处理的操作在批处理提交后才尝试执行。
解决这个问题的关键在于,当一个异步辅助函数参与到批处理操作中时,必须确保其在 batch.commit() 之前完成。这通过在调用异步函数时使用 await 关键字来实现:
const batch = getFirestore().batch(); // ... 其他批处理操作 // 关键:确保异步辅助函数在批处理提交前完成 await severGroupOwnerLinksWithUser(user.uid, batch); // ... 其他批处理操作 await batch.commit(); // 提交批处理
通过添加 await,我们强制 severGroupOwnerLinksWithUser 函数在其内部所有操作完成之前,阻塞当前函数的执行,从而确保所有对 batch 的修改都能在 batch.commit() 被调用时包含在内。
Firestore 的 array-contains 查询功能强大,但其与对象匹配的严格性有时会引起误解。然而,更深层次、更隐蔽的问题往往潜藏在异步编程的细节中。本文通过一个实际案例,强调了在 Firestore 批处理操作中,正确使用 await 关键字对于确保异步辅助函数按预期执行,并将其修改包含在最终提交的批处理中的重要性。理解并遵循这些最佳实践,将有助于开发者避免类似的陷阱,构建更健壮、更可靠的 Firestore 应用。
以上就是Firestore array-contains 查询与异步批处理操作的陷阱的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号