带有ARRAY_CONTAINS的DocumentDB SQL

cor*_*ore 8 sql azure-cosmosdb

我在https://www.documentdb.com/sql/demo上玩,这允许我查询示例文档,如下所示:

{
  "id": "19015",
  "description": "Snacks, granola bars, hard, plain",
  "tags": [
    {
      "name": "snacks"
    }
  ],
  "version": 1,
  "isFromSurvey": false,
  "foodGroup": "Snacks",
  "servings": [
    {
      "amount": 1,
      "description": "bar",
      "weightInGrams": 21
    }
  ]
}
Run Code Online (Sandbox Code Playgroud)

我很困惑ARRAY_CONTAINS().此查询返回结果:

SELECT root
FROM root 
WHERE ARRAY_CONTAINS(root.tags, { "name": "snacks" })
Run Code Online (Sandbox Code Playgroud)

但是,此查询不会:

SELECT root
FROM root 
WHERE ARRAY_CONTAINS(root.servings, { "description": "bar" })
Run Code Online (Sandbox Code Playgroud)

是什么赋予了?

如果这是C#,我将如何编写查询来说明我想要实现的目标:

var filteredDocs = docs.Where(d => d.Servings != null &&
                                   d.Servings.Length > 0 &&
                                   d.Servings.Any(s => s.Description == "bar"));
Run Code Online (Sandbox Code Playgroud)

它出现在第一示例查询root.tags因为作品{ "name": "snacks" }整个中对象root.tags阵列,而在第二个查询,{ "description": "bar" }一个字段中的root.servings对象.

如何修改第二个查询root.servings才能使用只知道服务description

Jim*_*ott 17

当您最初查看API时,不确定此功能是否可用,但ARRAY_CONTAINS现在支持最后的可选布尔值以提供部分匹配支持.

SELECT root
FROM root
WHERE ARRAY_CONTAINS(root.servings, { "description": "bar" }, true)
Run Code Online (Sandbox Code Playgroud)

下面是使用documentdb演示站点的示例,该站点查询包含存储的每个对象的多个字段的数组.

SELECT  *
FROM    food as f
WHERE   ARRAY_CONTAINS(f.servings, {"description":"bar"}, true)
Run Code Online (Sandbox Code Playgroud)


Lar*_*one 6

您的servings数组只有一个条目{"amount": 1, "description": "bar", "weightInGrams": 21}.

这应该适用于您的单个服务示例:

SELECT root
FROM root 
WHERE root.servings[0].description = "bar"
Run Code Online (Sandbox Code Playgroud)

但听起来这并不是你想要的.所以,假设你有这个:

{
  ...
  "servings": [
    {"description": "baz", ....},
    {"description": "bar", ....},
    {"description": "bejeweled", ....}
  ],
  ...
}
Run Code Online (Sandbox Code Playgroud)

并且您想要找到其中一个服务具有描述"bar"的文档,然后您可以使用此UDF:

function(servings, description) {
    var s, _i, _len;
    for (_i = 0, _len = servings.length; _i < _len; _i++) {
        s = servings[_i];
        if (s.description === description) {
            return true;
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

有了这个查询:

SELECT * FROM c WHERE udf.findServingsByDescription(c.servings, "bar")
Run Code Online (Sandbox Code Playgroud)

  • 它与标签是否相关无关.`ARRAY_CONTAINS`需要一组JSON基类型(String,Number)而不是Object.因此,一个标签数组(`["High","Medium"]`)符合数字数组(`[1,4,7]`)的要求,而你的例子没有. (3认同)

小智 5

请注意,这是一个效果很好的解决方法。

SELECT c.id FROM c JOIN a in c.companies where a.id = '{id}'
Run Code Online (Sandbox Code Playgroud)

在 Linq 中这将是

x => x.companies.Any(z => z.id == id)
Run Code Online (Sandbox Code Playgroud)