返回

如何在 Python Firebase 查询中排除特定文档 ID?

python

如何在 Python 中使用 Firebase 查询排除特定文档 ID?

你是否在使用 Firebase 开发应用程序时,遇到需要从查询结果中排除特定文档 ID 的情况?你是否尝试过使用 FieldPath.document_id() 配合 not-in 操作符,却陷入了 __key__ filter value must be a Key 错误的迷宫?

这个问题在 Firebase 开发中十分常见,特别是当你需要根据特定条件过滤文档 ID 时。幸运的是,Firebase 提供了多种方法来解决这个问题,让你可以轻松地绕过这个障碍。本文将为你提供清晰易懂的解决方案,并附带代码示例,帮助你使用 Python 在 Firebase 查询中排除特定的文档 ID。

深入问题:为何 FieldPath.document_id()not-in 操作符会导致错误?

当你尝试使用 FieldPath.document_id()not-in 操作符排除特定的文档 ID 时,Firebase 会抛出一个错误信息:__key__ filter value must be a Key

这是因为 not-in 操作符期待接收一个 Key 类型的值列表作为参数,而 FieldPath.document_id() 返回的却是一个字符串类型的字段名 __name__ ,而非实际的文档 ID。

因此,Firebase 无法将字段名直接识别为文档 ID,导致查询失败。

解决方案一:化整为零,使用多个 where 语句逐个排除

针对这个问题,我们可以采取一种简单直接的方案:使用多个 where 语句,并利用 != 操作符逐个排除需要过滤的文档 ID。

这种方法易于理解和实现,尤其适用于需要过滤的文档 ID 数量较少的情况。

以下是一个使用多个 where 语句的代码示例:

from firebase_admin import firestore

# 假设我们需要排除的文档 ID 列表
blocked_ids = ['123123', '232323']

# 初始化 Firestore 客户端
db = firestore.AsyncClient()

# 指定集合和文档路径
query_ref = db.collection('items').document('some-id-here').collection('other-items')

# 使用多个 where 语句排除特定的文档 ID
for blocked_id in blocked_ids:
    query_ref = query_ref.where(firestore.field_path.FieldPath.document_id(), '!=', blocked_id)

# 执行查询并获取结果
items = await query_ref.stream()

# 遍历并打印结果
async for item in items:
    print(f'{item.id} => {item.to_dict()}')

在这个例子中,我们首先定义了一个包含所有需要排除的文档 ID 的列表 blocked_ids

然后,我们遍历 blocked_ids 列表,并为每个需要排除的文档 ID 添加一个 where 语句,最终构建出一个包含所有过滤条件的 query_ref 对象。

最后,我们执行查询,并得到排除了指定文档 ID 的结果。

解决方案二:精确制导,使用 not-in 操作符和文档引用

如果需要过滤的文档 ID 数量较多,使用多个 where 语句可能会影响查询性能。

在这种情况下,我们可以采取另一种更精准高效的方法:使用 not-in 操作符和文档引用。

以下是使用 not-in 操作符和文档引用的代码示例:

from firebase_admin import firestore

# 假设我们需要排除的文档 ID 列表
blocked_ids = ['123123', '232323']

# 初始化 Firestore 客户端
db = firestore.AsyncClient()

# 指定集合和文档路径
collection_ref = db.collection('items').document('some-id-here').collection('other-items')

# 创建文档引用列表
blocked_docs = [collection_ref.document(id) for id in blocked_ids]

# 使用 not-in 操作符排除特定的文档引用
query_ref = collection_ref.where(firestore.field_path.FieldPath.document_id(), 'not-in', blocked_docs)

# 执行查询并获取结果
items = await query_ref.stream()

# 遍历并打印结果
async for item in items:
    print(f'{item.id} => {item.to_dict()}')

在这个例子中,我们首先创建了一个包含所有需要排除的文档引用的列表 blocked_docs

然后,我们使用 not-in 操作符和 blocked_docs 列表构建查询条件,将需要排除的文档 ID 精确地传递给 Firebase。

这种方法避免了使用多个 where 语句可能带来的性能问题,尤其适用于需要过滤大量文档 ID 的情况。

总结:选择最适合你的方法

在 Python 中使用 Firebase 查询排除特定的文档 ID 并不复杂,你可以根据实际情况选择使用多个 where 语句或 not-in 操作符和文档引用。

如果需要过滤的文档 ID 数量较少,使用多个 where 语句更加简单直观。

如果需要过滤的文档 ID 数量较多,使用 not-in 操作符和文档引用可以提高查询性能。

希望本文能够帮助你解决在 Firebase 查询中排除特定文档 ID 的问题。

常见问题解答

1. 为什么我的查询没有返回任何结果?

请检查以下几点:

  • 确保 blocked_ids 列表中的文档 ID 存在于你的集合中。
  • 确保你的安全规则允许读取集合中的文档。
  • 如果使用多个 where 语句,请确保所有条件都正确。

2. 我可以使用哪些其他方法来排除文档 ID?

除了本文介绍的两种方法外,你还可以使用以下方法:

  • 在客户端过滤结果:在获取查询结果后,使用循环遍历结果并排除不需要的文档 ID。
  • 使用 Cloud Functions:编写一个 Cloud Function 来执行查询并返回过滤后的结果。

3. 使用多个 where 语句和使用 not-in 操作符哪种方法性能更好?

通常情况下,使用 not-in 操作符和文档引用的性能更好,因为它可以将所有需要排除的文档 ID 一次性传递给 Firebase。

4. 我可以在 not-in 操作符中使用多少个文档引用?

根据 Firebase 官方文档,not-in 操作符最多支持 10 个元素。如果需要排除的文档 ID 超过 10 个,建议使用其他方法,例如在客户端过滤结果或使用 Cloud Functions。

5. 我还有其他问题,在哪里可以获得帮助?

你可以查阅 Firebase 官方文档,或在 Stack Overflow 等技术论坛上寻求帮助。