首页 文章

DocumentDb存储库一般查询子文档

提问于
浏览
1

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

背景

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

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

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; }

}

在文档资源管理器中,我可以看到我有这样的类结构的一个实例,如下所示:

{
  "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;
    }

问题

但是,如果我想要检索的只是员工而不管他们属于哪个公司,我不确定如何在存储库类中编写一个方法来完成此任务 .

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

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

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

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

1 回答

  • 3

    无论公司是什么,我都想找回员工

    如果我理解正确,您希望根据客户的员工 property 查询员工 . 如果是这种情况,我们可以使用SQL执行以下操作,我们只需要根据需要更改where < filter_condition > .

    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
    }
    

相关问题