如何查询特定类型然后获取基础文档

时间:2018-08-24 22:00:42

标签: c# linq azure azure-cosmosdb document-database

我要尝试的是按特定文档类型进行查询

MyType foo = client.CreateDocumentQuery<MyType>(documentCollectionUri)
   .ToList()
   .FirstOrDefault(d => d.SomeProperty == someProperty);

然后用另一个替换该文档。看来唯一可用的方法是

public Task<ResourceResponse<Document>> ReplaceDocumentAsync(Uri documentUri, object document, RequestOptions options = null);

public Task<ResourceResponse<Document>> ReplaceDocumentAsync(Document document, RequestOptions options = null);

public Task<ResourceResponse<Document>> ReplaceDocumentAsync(string documentLink, object document, RequestOptions options = null);

所有这些都需要Document或其id

那么,如何从foo获取这些值?不可能吗?

2 个答案:

答案 0 :(得分:0)

首先,您应该像这样进行查询:

List<MyType> foo = client.CreateDocumentQuery<MyType>(documentCollectionUri)
  .Where(d => d.SomeProperty == someProperty);
  .ToList();

否则,在过滤属性之前,您将从db获取所有文档。

对于您的实际问题,您有两种选择:

1)将id用作文档的一部分

CosmosDB将在保存时自动设置ID,并在检索文档时将其反序列化为字段。然后,您可以使用ID进行替换操作。

class MyType{

 [Newtonsoft.Json.JsonProperty(PropertyName="id")]      
public string Id {get; set;}
}
// Get documentUri by:
UriFactory.CreateDocumentUri(string databaseId, string collectionId, string documentId)
public Task<ResourceResponse<Document>> ReplaceDocumentAsync(Uri documentUri, object document, RequestOptions options = null);

2)将查询定义与查询执行分开

您可以将不同类型用于查询定义和响应反序列化。因此,您可以针对MyType进行查询,并将响应反序列化为Document

var query = client.CreateDocumentQuery<MyType>(documentCollectionUri)
  .Where(d => d.SomeProperty == someProperty)
  .AsDocumentQuery();

var response = await query.ExecuteNextAsync<Document>(cancellationToken).ConfigureAwait(false);
var document = response.FirstOrDefault();

答案 1 :(得分:0)

首先,问题表达的方式还不清楚。

MyType foo = client.CreateDocumentQuery<MyType>(documentCollectionUri)
   .ToList()
   .FirstOrDefault(d => d.SomeProperty == someProperty);

如果您在同一问题中存储多种不同类型的对象,则使用T参数MyType不能保证您将获得的结果只会是MyType个结果,但而是匹配表达式的任何内容都将被映射并以MyType的形式返回。 CosmosDB SDK中没有其他过滤可以保证查询只会在该类型的对象上进行,因为CosmosDB没有该上下文。

使用ReplaceDocumentAsync方法执行此操作的唯一可靠方法是(如Alex AIT所说)在对象上添加带有Id属性的[JsonProperty("id")]属性。考虑到它是DTO而不是Domain对象,因此该属性应该存在,并且对其他功能(例如删除等)确实有帮助。

我强烈建议您查看Cosmonaut,它是CosmosDB ORM,它也可以处理基于类型的集合共享以及您试图实现的相同查询和更新,而不必弄乱任何此类逻辑。

免责声明:我是宇航员的创建者

另一方面,您不应在使用ToList()创建的IQueryable上使用CreateDocumentQuery,而应在其上使用.AsDocumentQuery()方法,然后使用while(query.HasMoreResults)的组合然后使用query.ExecuteNextAsync()方法来正确使用分页的CosmosDB功能。