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

时间:2018-01-27 02:01:37

标签: c# azure azure-cosmosdb

我在Azure CosmosDB中有一个集合,每个文档都是这样的:

{
  "id": "random",
  "TeacherName": "Ben",
  "Students": [
    {
      "Name": "John",
      "Telephone": ""
    },
    {
      "Name": "Mary",
      "Telephone": ""
    }
  ],
}

TeacherName是字符串,学生是学生列表

我需要这样做:给定一个用户名(user1),查询并返回所有文件,教师姓名是" user1"或者有一个名字为#34; user1"的学生。

我尝试了一些选项,但不能这样做。

我到目前为止找到的最接近的解决方案是使用.SelectMany(),但我发现.SelectMany会进行连接,并会复制返回结果。

这是我的疑问:

client.CreateDocumentQuery().SelectMany((x) => x.Students.Where(s=>s.Name == "user1" || x.TeacherName == "user1")   

如果只有上面的示例文档在集合中,当我搜索用户名" Ben"时,将返回2条记录((结果数)*(学生数))。我必须在客户端删除副本,并且分页有点破碎。

是否可以发出单个查询来实现我的需求?

1 个答案:

答案 0 :(得分:3)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>{% block title %}Welcome!{% endblock %}</title>

    {% block stylesheets %}
        <link rel="stylesheet" href="{{ asset('build/vendor.css') }}"/>
        <link rel="stylesheet" href="{{ asset('build/style.css') }}"/>
        <link rel="stylesheet" href="{{ asset('build/app.css') }}"/>
    {% endblock %}
</head>
<body class="pal">
<div id="app">

    <ingredient-search></ingredient-search>

</div>
{% block javascripts %}
    <script src="{{ asset('build/manifest.js') }}"></script>
    <script src="{{ asset('build/vendor.js') }}"></script>
    <script src="{{ asset('build/style.js') }}"></script>
    <script src="{{ asset('build/app.js') }}"></script>
{% endblock %}
</body>
</html>

实际上代码中的client.CreateDocumentQuery().SelectMany((x) => x.Students.Where(s=>s.Name == "user1" || x.TeacherName == "user1") 方法类似于下面的sql:

SelectMany

输出

SELECT c.id from c
join x  in c.Students
where c.TeacherName ='Ben' or x.Name = 'Ben'

如果有加入,则会出现重复数据。据我所知,Azure Cosmos DB不支持自动删除重复数据(如传统数据库中的[ { "id": "1" }, { "id": "1" } ] 关键字)。

似乎无法在查询SQL级别中删除重复数据。

如果您不想在本地循环中处理查询结果集,我强烈建议您使用stored procedure处理Azure Cosmos DB中的结果数据,以释放当地的压力服务器

或者,如果您的数据不是太大,您可以直接在存储过程中完成查询。请参考以下js代码:

Distinct

更新答案:

我检查了Azure Cosmos DB pricing details。然后它没有表明存储过程比单个查询更昂贵。实际上,成本取决于// 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.'); } Rus取决于查询的复杂性和并发量等。

您可以参考R document。此外,您可以通过http请求标头知道RU费用:RuS。请看这个有用的痕迹: How to caculate the Azure Cosmos DB RU used in server side scripting

希望它对你有所帮助。