我在 Azure CosmosDB 中有一个集合,每个文档如下所示:
{
"id": "random",
"TeacherName": "Ben",
"Students": [
{
"Name": "John",
"Telephone": ""
},
{
"Name": "Mary",
"Telephone": ""
}
],
}
TeacherName 是字符串,Students 是学生列表
我需要做的:给定一个用户名(user1),查询并返回所有文档,要么老师的名字是“user1”,要么有一个学生的名字是“user1”。
我尝试了一些选项,但无法做到。
到目前为止,我发现的最接近的解决方案是使用 .SelectMany()
,但我发现 .SelectMany
会执行联接并重复返回结果。
这是我的查询:
client.CreateDocumentQuery().SelectMany((x) => x.Students.Where(s=>s.Name == "user1" || x.TeacherName == "user1")
如果集合中只有上述示例文档,当我搜索用户名“Ben”时,将返回2条记录((结果数)*(学生数))。我必须删除客户端的重复项,并且分页有点损坏。
是否可以发出单个查询来实现我的需要?
最佳答案
client.CreateDocumentQuery().SelectMany((x) => x.Students.Where(s=>s.Name == "user1" || x.TeacherName == "user1")
实际上代码中的SelectMany
方法类似于下面的sql:
SELECT c.id from c
join x in c.Students
where c.TeacherName ='Ben' or x.Name = 'Ben'
输出
[
{
"id": "1"
},
{
"id": "1"
}
]
如果存在连接,就会出现重复数据。据我所知,Azure Cosmos DB 尚不支持自动删除重复数据(如传统数据库中的 Distinct
关键字)。
好像没有办法去掉查询SQL级别的重复数据。
如果您不想在本地循环中处理查询结果集,我强烈建议您使用 stored procedure处理Azure Cosmos DB中的结果数据,释放本地服务器的压力。
或者,如果您的数据不是太大,也可以直接在存储过程中完成查询。请引用如下js代码:
// SAMPLE STORED PROCEDURE
function sample(idsArrayString,courses) {
var collection = getContext().getCollection();
var isAccepted = collection.queryDocuments(
collection.getSelfLink(),
'SELECT * FROM root r',
function (err, feed, options) {
if (err) throw err;
if (!feed || !feed.length) getContext().getResponse().setBody('no docs found');
else {
var returnResult = [];
for(var i = 0;i<feed.length;i++){
var doc = feed[i];
if(doc.TeacherName == 'Ben'){
returnResult.push(feed[i]);
break;
}
var std = doc.Students;
for (var s in std) {
if(s.Name == 'Ben'){
returnResult.push(feed[i]);
break;
}
}
}
getContext().getResponse().setBody(returnResult);
}
});
if (!isAccepted) throw new Error('The query was not accepted by the server.');
}
更新答案:
我检查了Azure Cosmos DB pricing details 。那么它并没有表明存储过程比单个查询更昂贵。实际上,成本取决于Rus
,RuS
取决于查询的复杂度和并发量等。
您可以引用RU document 。另外,您还可以通过http请求 header 了解RU的费用:x-ms-request-charge
。请查看这个有用的跟踪:
How to caculate the Azure Cosmos DB RU used in server side scripting .
希望对您有帮助。
关于c# - 如何在Cosmos Db中查询子文档(列表类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48471904/