我在CosmosDB中有一个 ProductDocument
模型,代表一个产品 . 在该模型中,有一个子文档 contributors
,其中包含为产品做出贡献的人员 . 每个贡献者都有 role
.
现在我一直在尝试一个需要的查询:
-
仅选择
ProductDocument
,contributor.roleDescription
为 Author -
仅选择
ProductDocument
,division
为 Pub 1 -
仅包含
contributors
子文档,结果集中contributor.roleDescription
为 Author .
现在我正在努力:
- 上面选择的第3部分 . 我如何完成此位,因为我的结果集包括
contributor.roleDescription
和 Author 和 Illustrator
示例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 回答
Azure CosmosDB现在支持子查询 . 使用子查询,您可以通过两种方式执行此操作,但存在细微差别:
这假定您需要首先对分区“Pub 1”进行过滤,然后使用ARRAY表达式对子查询进行过滤 .
这将在标有“c”的属性中将原始文档与“Pub 1”分区一起投影,并在标记为“contributors”的属性中分别将过滤的贡献者数组分开 . 您可以为您的过滤贡献者引用此贡献者数组,并忽略文档中的那个 .
这将做你想要的,但很明显,如果你有多个贡献者,你想表明它可能不会做你想要的 - 你很难说你的问题是否是你想要的
输出是:
请注意,贡献者不是列表,它是单个值,因此如果多个贡献者匹配过滤器,那么您将获得多次返回的相同产品 .