c# - 如何在Cosmos Db中查询子文档(列表类型)

标签 c# azure azure-cosmosdb

我在 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 。那么它并没有表明存储过程比单个查询更昂贵。实际上,成本取决于RusRuS取决于查询的复杂度和并发量等。

您可以引用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/

相关文章:

c# - 为什么 ReadOnlyObservableCollection.CollectionChanged 不公开?

c# - 如何获取字符串中除第一个单词以外的所有单词

wcf - 通过附加到请求线程的安全主体访问声明,而不是 AuthorizationContext

azure - Cosmos Db 需要哪些权限才能访问 Azure 门户中的数据库并查看数据

c# - 无法关闭由 Task.Factory.StartNew 启动的任务

c# - 如何在 asp.net MVC4 中存储文件路径

Azure 应用服务自定义域不支持 www 前缀

sql - Azure Sql Server (PaaS) 可以拥有的数据库数量是否有限制?和/或 Azure Sql Server 可以容纳的数据量是否有大小限制?

azure - DocumentDB 用户定义的性能定价

database - Azure Cosmos Document DB,可能有关系链接吗?