【问题标题】:Firestore WhereIn Query with FieldPath.DocumentId is throwing exception带有 FieldPath.DocumentId 的 Firestore WhereIn 查询引发异常
【发布时间】:2020-05-20 06:50:08
【问题描述】:

尝试根据 DocumentID 列表从集合中获取少量文档,但无法使用 WhereIn 和 FieldPath 进行以下操作。 Nuget 版本 Google.Cloud.Firestore v1.1.0

public async Task<IEnumerable<T>> GetByDocumentIdWhereIn(IEnumerable<string> documentIds)
{
    CollectionReference ref= FirestoreDb.Collection(_collectionName);
    Query query = ref.WhereIn(FieldPath.DocumentId, documentIds);
    QuerySnapshot querySnapshot = await query.GetSnapshotAsync();
    ...
}

当使用几个 documentIds 执行时,我收到以下错误。

RpcException: Status(StatusCode=InvalidArgument, Detail="__key__ filter value must be a Key")
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Grpc.Core.Internal.ClientResponseStream+<MoveNext>d__5.MoveNext() in ClientResponseStream.cs
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Linq.AsyncEnumerable+<ForEachAsync_>d__174.MoveNext() in ForEach.cs
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Google.Cloud.Firestore.Query+<GetSnapshotAsync>d__54.MoveNext() in Query.cs
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
System.Runtime.CompilerServices.TaskAwaiter.GetResult()

有什么想法吗?

【问题讨论】:

  • 嗯。我不知道这是否是仅限客户端的限制,或者即使我们允许它在客户端它是否会在服务器端失败。会调查。我创建了github.com/googleapis/google-cloud-dotnet/issues/4981 来跟踪它。
  • 顺便说一句,除了一次性获取一堆文档之外,您还需要其他功能吗? FirestoreDb.GetAllSnapshotsAsync 可能是一种更简单的方法。
  • 啊 - 我误读了异常。这是已经是服务器端的限制。我需要询问 Firestore 团队。
  • 如果我理解您提到的服务器端/客户端术语,C# 库被视为从底层 api(服务器端)获取数据的客户端库?而且因为这是潜在的 api 问题,所以目前没有明显的解决方法?
  • 昨天我发布了 Google.Cloud.Firestore 2.1.0,它应该可以让你的原始代码工作。

标签: c# google-cloud-platform google-cloud-firestore


【解决方案1】:

注意:此答案是在 Google.Cloud.Firestore 2.1.0 发布之前编写的。从 2.1.0 开始,原始代码应该可以工作。


这是服务器生成的异常,但可以在客户端转换查询以使其正常工作。如果提供的值是 DocumentReference 值而不是字符串,则查询有效。

这意味着你现在可以像这样修复你的代码:

CollectionReference coll = FirestoreDb.Collection(_collectionName);
var docRefs = documentIds.Select(id => coll.Document(id)).ToList();
Query query = coll.WhereIn(FieldPath.DocumentId, docRefs);
QuerySnapshot querySnapshot = await query.GetSnapshotAsync();

未来我们希望自动为您执行此操作;这方面的进展将在this GitHub issue 上进行跟踪。

请注意,如果您只是想要获取文档快照的集合,并且您拥有(或可以创建)DocumentReference 值序列,则另一种方法是使用 FirestoreDb.GetAllSnapshotsAsync。

【讨论】:

  • @skjagini:这是一个完全合理的期望——我希望我们将来能够在客户端库中使用它,尽管我不希望在 6 月之前实现。
  • 听起来不错,如果我们可以改进 Firestore 网站上的方法签名或示例,这将对许多人有所帮助。例如:public Query WhereIn(FieldPath fieldPath, IEnumerable values);乍一看有点混乱。
  • @skjagini:我们绝对不能更改方法签名——部分原因是为了兼容性,部分原因是它可以处理一系列整数或字符串,或日期/时间值等(如果您查询的不是文档引用,例如文本字段,则字符串会很好。)
  • @skjagini:有什么理由编辑我的答案吗?此处应该无需致电ToList()。据我所知,源应该只评估一次,无需创建列表。
  • @skjagini:我现在明白为什么如果没有 ToList,目前这会失败,我已经收到了一个拉取请求来解决这个问题。并不是说您从 2.1.0 开始就完全需要 LINQ 查询,但是能够更频繁地使用 LINQ 真是太好了 :) github.com/googleapis/google-cloud-dotnet/pull/5022
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 2020-08-10
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 2014-03-22
  • 2011-01-21
相关资源
最近更新 更多