首页 文章

CosmosDB - SubDocument Delselecting - LINQ Query

提问于
浏览
0

我在CosmosDB中有一个 ProductDocument 模型,代表一个产品 . 在该模型中,有一个子文档 contributors ,其中包含为产品做出贡献的人员 . 每个贡献者都有 role .

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

  • 仅选择 ProductDocumentcontributor.roleDescriptionAuthor

  • 仅选择 ProductDocumentdivisionPub 1

  • 仅包含 contributors 子文档,结果集中 contributor.roleDescriptionAuthor .

现在我正在努力:

  • 上面选择的第3部分 . 我如何完成此位,因为我的结果集包括 contributor.roleDescriptionAuthorIllustrator

示例Cosmos模型:

[

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

    }]

这是我在数据资源管理器中一直在玩的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"
            }

        ]

    }

编辑:

  • 如果其中一个子文档 contributor.roleDescription 等于Author,我想过滤 Product . 因此,如果产品记录没有't include a Author contributor I don't想要它

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

  • 你可以拥有 ProductDocuments 的集合 .

  • 有关流畅的LINQ语法的帮助将有很大帮助 .

2 回答

  • 2

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

    • 您可以在投影中使用带有子查询的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表达式对子查询进行过滤 .

    • 或者,如果您想要整个文档以及过滤的贡献者,您可以这样做:
    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”的属性中分别将过滤的贡献者数组分开 . 您可以为您的过滤贡献者引用此贡献者数组,并忽略文档中的那个 .

  • 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"
            }
        }
    ]
    

    请注意,贡献者不是列表,它是单个值,因此如果多个贡献者匹配过滤器,那么您将获得多次返回的相同产品 .

相关问题