通常用于查询子文档的DocumentDb存储库

时间:2017-07-04 16:53:42

标签: azure-cosmosdb

在DocumentDb中,是否可以搜索符合特定条件的子文档而无需在查询中涉及父类?

背景

我(尝试开始)使用在创建新的Azure Cosmos数据库帐户时在Azure门户中自动生成的DocumentDbRepository.cs。但是,显而易见的是,这仅仅是一个起点,需要为个别情景做一些额外的工作。

在C#Console应用程序(.NET Core)中,我在公司和员工之间有一个简单的父子关系:

public class Customer
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "name")]
    public string Name { get; set; }

    [JsonProperty(PropertyName = "location")]
    public string Location { get; set; }

    [JsonProperty(PropertyName = "employees")]
    public List<Employee> Employees { get; set; }

    public Customer()
    {
        Employees = new List<Employee>();
    }
}

public class Employee
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "firstName")]
    public string FirstName { get; set; }

    [JsonProperty(PropertyName = "lastName")]
    public string LastName { get; set; }

    [JsonProperty(PropertyName = "sales")]
    public double Sales { get; set; }

}

在Document Explorer中,我可以看到我有这样一个类结构的实例:

{
  "id": "7",
  "name": "ACME Corp",
  "location": "New York",
  "employees": [
    {
      "id": "c4202793-da55-4324-88c9-b9c9fe8f4b6c",
      "firstName": "John",
      "lastName": "Smith",
      "sales": 123
    }
  ]
}

如果我想让所有公司符合某个标准,那么使用生成的DocumentDbRepository.cs方法将是一个相当简单的操作:

DocumentDBRepository<Customer>.Initialize();
var customers = DocumentDBRepository<Customer>.GetItemsAsync(p => p.Location.Equals("New York")).Result;

...作为参考,Microsoft方法生成的GetItemsAsync()如下所示:

    public static async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate)
    {
        IDocumentQuery<T> query = client.CreateDocumentQuery<T>(
                UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId),
                new FeedOptions { MaxItemCount = -1 })
            .Where(predicate)
            .AsDocumentQuery();

        List<T> results = new List<T>();
        while (query.HasMoreResults)
        {
            results.AddRange(await query.ExecuteNextAsync<T>());
        }

        return results;
    }

问题

但是,如果我想要检索 ONLY EMPLOYEES ,无论他们属于哪个公司,我都不确定如何在存储库类中编写一个方法来完成此任务。

首先,我认为我需要某种类型的属性,因此我可以区分客户与员工的区别(与我可能也希望在同一集合中添加的其他域类类型相比)。

其次,我可能会查询为所有查询使用该类型属性,而不使用似乎只适用于根数据的DocumentDbRepository.cs方法。换句话说,DocumentDbRepository.cs方法似乎只关注非分层实体。

但这就是事情崩溃的地方......鉴于这个示例存储库类的通用特性,我无法将查询子文档/子项所需的点连接起来。

我只是要求在这里向正确的方向推进。谢谢。

1 个答案:

答案 0 :(得分:3)

  

无论公司是什么,我都想检索员工

如果我理解正确,您希望根据员工查询员工&#39;来自客户的财产。如果是这种情况,我们可以使用SQL执行以下操作,我们只需要更改where&lt; filter_condition &gt;我们想要的。

SELECT c as employees
FROM c IN Customer.employees
WHERE c.firstName = 'John' 

我使用Azure门户网站提到的文档进行测试,它可以正常使用。

enter image description here

以下是c#演示代码:

var endpointUrl = "https://yourdocumentdbname.documents.azure.com:443/";
var authorizationKey = "xxxxx";
var databaseId = "database name";
var collectionId = "collecton name";
var client =  new DocumentClient(new Uri(endpointUrl), authorizationKey);
var sql = "SELECT c as employee FROM c IN Customer.employees WHERE c.firstName = 'xx'";
var collection = client.CreateDocumentCollectionIfNotExistsAsync(
            UriFactory.CreateDatabaseUri(databaseId), new DocumentCollection
            {
                Id = collectionId

            }).Result.Resource;
var query = client.CreateDocumentQuery(collection.SelfLink, sql).AsDocumentQuery();

while (query.HasMoreResults)
{
  var documents =  query.ExecuteNextAsync().Result;
  //do something
}