我在CosmosDB中有一个ProductDocument
模型,它代表一个产品。在该模型中,有一个子文档contributors
,其中包含谁对产品做出了贡献。每个贡献者都有一个role
。
现在我一直在尝试一个查询,该查询需要:
ProductDocument
为{strong>作者 contributor.roleDescription
ProductDocument
为{strong> Pub 1 division
contributors
为{strong> Author 的contributor.roleDescription
子文档。现在我正在努力:
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"
}
]
}
编辑:
如果子文档Product
之一等于Author,我想对contributor.roleDescription
进行过滤。因此,如果“产品”记录中不包含“作者”贡献者,我就不希望它
我想包含每个等于 Author 的contributor
子文档。因此,如果Product
有多个作者贡献者子文档,我想包括它们,但要排除 Illustrator 者。
您可能拥有ProductDocuments
的集合。
对流利的LINQ语法的帮助会很有帮助。
答案 0 :(得分:3)
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”的属性中将已过滤的贡献者数组单独投影。您可以为过滤的贡献者引用这个贡献者数组,而忽略文档中的那个。
答案 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"
}
}
]
请注意,贡献者不是列表,而是一个值,因此,如果有多个贡献者与过滤器匹配,那么您将获得多次返回相同产品的信息。