【问题标题】:DocumentDb: Get the first documentDocumentDb:获取第一个文档
【发布时间】:2019-06-04 16:50:18
【问题描述】:

是否有从查询中获取第一个文档的有效方法?通常这将使用FirstOrDefault() 与 LINQ 收集或在 SQL 中使用 TOP

假设集合看起来像这样:

{
    name: "John",
    position: 3
},
{
    name: "Mary",
    position: 1
},
{
    name: "Peter",
    position: 2
}

我只需要检索具有最高价值位置的单个文档。 IE。本例中的“Mary”文档。

使用 C# SDK,我必须执行以下操作:

Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
    .Where(somethingOtherCriteria);
    .OrderByDescending(x => x.Position)
    .AsEnumerable()
    .FirstOrDefault());

这将检索集合中的所有文档(在应用相关过滤器之后),然后从列表中获取第一个。这仍然会通过网络传输数千份不相关的文件。

是不是不能在服务器上执行FirstOrDefault()

【问题讨论】:

    标签: azure-cosmosdb


    【解决方案1】:

    一个选项是将最大响应大小设置为 1,并仅从查询迭代器中获取第一页:

    var query = client.CreateDocumentQuery<Family>(collectionLink, "SELECT * FROM myCollection", new FeedOptions { MaxItemCount = 1 }).AsDocumentQuery();
    var feedResponse = await query.ExecuteNextAsync<Family>();
    

    【讨论】:

    • 我不想这么说,但这是不正确的。我不怪你认为它是,因为我一直在想同样的事情,直到我发现,令我非常懊恼的是,事实并非如此。 ExecuteNextAsync() 按查询过滤页面,而不是结果集。巧合的是,您上面的代码将起作用,因为没有 WHERE 子句。如果您的查询包含一个排除所有第一页的 WHERE 子句(或者在本例中为单个结果,因为您使用的页面大小为 1),即使存在一个结果,您也将无法返回结果。
    【解决方案2】:

    你已经接近了。跳过 AsEnumerable() 并执行以下操作:

    var query = Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
        .Where(somethingOtherCriteria);
        .OrderByDescending(x => x.Position)
        .AsDocumentQuery();
    
    while (query.HasMoreResults)
        foreach (var document in await q.ExecuteNextAsync<T>(cancellationToken))
            return document;
    

    如果您这样做,您实际上不会返回任何结果,而是返回您想要的结果。问题是,您必须对每一页结果运行 ExecuteNextAsync(),直到获得具有所需结果的页面——但其他结果不会通过网络传输,也不会反序列化为 C# 引用类型.

    【讨论】:

      【解决方案3】:

      根据https://feedback.azure.com/forums/263030-azure-cosmos-db/suggestions/6771773-add-support-for-single-entity-retrieval-instead-of

      Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
          .Where(somethingOtherCriteria);
          .OrderByDescending(x => x.Position)
          .Take(1)
          .AsEnumerable()
          .FirstOrDefault());
      

      【讨论】:

        【解决方案4】:

        您正在寻找 Take(),这是在查询中映射到 TOP 的 Linq 函数。所以你想要类似的东西

                var query = client.CreateDocumentQuery<MyType>(collectionAddress)
                    .Where(x => x.Value == myValue)
                    .Take(1);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-05-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-09-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多