CosmosDB-子文档删除-LINQ查询

时间:2018-06-26 12:09:52

标签: linq azure-cosmosdb azure-cosmosdb-sqlapi

我在CosmosDB中有一个ProductDocument模型,它代表一个产品。在该模型中,有一个子文档contributors,其中包含谁对产品做出了贡献。每个贡献者都有一个role

现在我一直在尝试一个查询,该查询需要:

  1. 仅选择ProductDocument为{strong>作者
  2. contributor.roleDescription
  3. 仅选择ProductDocument为{strong> Pub 1
  4. division
  5. 在结果集中仅包含contributors为{strong> Author 的contributor.roleDescription子文档。

现在我正在努力:

  1. 上面选择的第3部分。我的结果集要同时包含 Author 和{strong> Illustrator
  2. contributor.roleDescription

宇宙模型示例:

[

    {
        "id": "1",
        "coverTitle": "A Title",
        "pubPrice": 2.99,
        "division" :"Pub 1",
        "Availability": {
            "code": "20",
            "description": "Digital No Stock"
        },
        "contributors": [
            {
                "id": 1,
                "firstName": "Brad",
                "lastName": "Smith",
                "roleDescription": "Author",
                "roleCode": "A01"
            },
            {
                "id": 2,
                "firstName": "Steve",
                "lastName": "Bradley",
                "roleDescription": "Illustrator",
                "roleCode": "A12"
            }
        ]

    },
    {
        "id": "2",
        "coverTitle": "Another Title",
        "division" :"Pub 2",
        "pubPrice": 2.99,
        "Availability": {
            "code": "50",
            "description": "In Stock"
        },
        "contributors": [
            {
                "id": 1,
                "firstName": "Gareth Bradley",
                "lastName": "Smith",
                "roleDescription": "Author",
                "roleCode": "A01"
            }
        ]

    }]

这是我在 Data Explorer 中一​​直使用的SQL:

SELECT VALUE p
FROM Products p
JOIN c IN p.contributors
WHERE c.roleDescription = 'Author'
AND p.division = 'Pub 1'

这是我通过服务查询的LINQ:

        var query = client.CreateDocumentQuery<ProductDocument>(
            UriFactory.CreateDocumentCollectionUri("BiblioAPI", "Products"),
            new FeedOptions
            {
                MaxItemCount = -1,
                EnableCrossPartitionQuery = true
            }
            ) 
            .SelectMany(product  => product.Contributors
                .Where(contributor => contributor.RoleDescription == "Author")
                .Select(c => product)
                .Where(p => product.Division == "Pub 1"))
            .AsDocumentQuery();

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

它选择了正确的记录,但是如何取消选择贡献者的 Illustrator 子文档,因为目前我得到以下信息:

   {
        "id": "1",
        "coverTitle": "A Title",
        "pubPrice": 2.99,
        "division" :"Pub 1",
        "Availability": {
            "code": "20",
            "description": "Digital No Stock"
        },
        "contributors": [
            {
                "id": 1,
                "firstName": "Brad",
                "lastName": "Smith",
                "roleDescription": "Author",
                "roleCode": "A01"
            },
            {
                "id": 2,
                "firstName": "Steve",
                "lastName": "Bradley",
                "roleDescription": "Illustrator",
                "roleCode": "A12"
            }
        ]

    }

但是我想要的是以下输出,但不包括Illustrator贡献者子文档:

 {
        "id": "1",
        "coverTitle": "A Title",
        "pubPrice": 2.99,
        "division" :"Pub 1",
        "Availability": {
            "code": "20",
            "description": "Digital No Stock"
        },
        "contributors": [
            {
                "id": 1,
                "firstName": "Brad",
                "lastName": "Smith",
                "roleDescription": "Author",
                "roleCode": "A01"
            }

        ]

    }

编辑:

  1. 如果子文档Product之一等于Author,我想对contributor.roleDescription进行过滤。因此,如果“产品”记录中不包含“作者”贡献者,我就不希望它

  2. 我想包含每个等于 Author contributor子文档。因此,如果Product有多个作者贡献者子文档,我想包括它们,但要排除 Illustrator 者。

  3. 您可能拥有ProductDocuments的集合。

  4. 对流利的LINQ语法的帮助会很有帮助。

2 个答案:

答案 0 :(得分:3)

Azure CosmosDB现在支持子查询。使用子查询,您可以通过两种方式执行此操作,但有细微差别:

  1. 您可以在投影中的子查询中使用ARRAY表达式,过滤掉不需要的贡献者,并投影所有其他属性。该查询假设您需要一个选择属性列表以从数组中投影出来。

    SELECT c.id, c.coverTitle, c.division, ARRAY(SELECT VALUE contributor from contributor in c.contributors WHERE contributor.roleDescription = "Author") contributors
    FROM c 
    WHERE c.division="Pub 1"
    

这假定您需要首先过滤“ Pub 1”分区,然后再过滤带有ARRAY表达式的子查询。

  1. 或者,如果您想要整个文档以及过滤的贡献者,则可以执行以下操作:

    SELECT c, ARRAY(SELECT VALUE contributor from contributor in c.contributors  WHERE contributor.roleDescription = "Author") contributors 
    FROM c 
    WHERE c.division="Pub 1"
    

这将在标记为“ c”的属性中将“ Pub 1”划分为原始文档,并在标记为“ contributors”的属性中将已过滤的贡献者数组单独投影。您可以为过滤的贡献者引用这个贡献者数组,而忽略文档中的那个。

答案 1 :(得分:0)

这将满足您的要求,但是很显然,如果您有多个贡献者想要展示它,可能并不能完全满足您的要求-很难说出您到底是不是想要的那个问题

SELECT p.id, p.coverTitle, p.pubPrice, p.division, p.Availability, c as contributors
FROM Products p
JOIN c IN p.contributors
WHERE c.roleDescription = 'Author'
AND p.division = 'Pub 1'

,输出为:

[
    {
        "id": "1",
        "coverTitle": "A Title",
        "pubPrice": 2.99,
        "division": "Pub 1",
        "Availability": {
            "code": "20",
            "description": "Digital No Stock"
        },
        "contributors": {
            "id": 1,
            "firstName": "Brad",
            "lastName": "Smith",
            "roleDescription": "Author",
            "roleCode": "A01"
        }
    }
]

请注意,贡献者不是列表,而是一个值,因此,如果有多个贡献者与过滤器匹配,那么您将获得多次返回相同产品的信息。