文档数据库 SQL 和 ARRAY_CONTAINS
DocumentDB SQL with ARRAY_CONTAINS
我正在玩 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
}
]
}
我对 ARRAY_CONTAINS()
感到困惑。此查询 returns 结果:
SELECT root
FROM root
WHERE ARRAY_CONTAINS(root.tags, { "name": "snacks" })
但是,这个查询没有:
SELECT root
FROM root
WHERE ARRAY_CONTAINS(root.servings, { "description": "bar" })
什么给了?
如果这是 C#,我将如何编写查询来说明我想要实现的目标:
var filteredDocs = docs.Where(d => d.Servings != null &&
d.Servings.Length > 0 &&
d.Servings.Any(s => s.Description == "bar"));
root.tags
上的第一个示例查询似乎有效,因为 { "name": "snacks" }
是 root.tags
数组中的 整个 对象,而在第二个查询,{ "description": "bar" }
只是 root.servings
对象中的 一个字段 。
如何修改 root.servings
上的第二个查询,使其只知道服务 description
?
编辑:ARRAY_CONTAINS 现在支持部分匹配,正如 Jim Scott 在下面指出的那样,我认为这是比这个公认的更好的答案。
你servings
数组只有一个条目{"amount": 1, "description": "bar", "weightInGrams": 21}
。
这应该适用于您的单份服务示例:
SELECT root
FROM root
WHERE root.servings[0].description = "bar"
但听起来这不是您要查找的内容。所以,假设你有这个:
{
...
"servings": [
{"description": "baz", ....},
{"description": "bar", ....},
{"description": "bejeweled", ....}
],
...
}
并且您想查找其中一份服务具有描述 "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;
}
使用此查询:
SELECT * FROM c WHERE udf.findServingsByDescription(c.servings, "bar")
如 Larry Maccherone 所述,使用 UDF 的缺点是它不使用集合的索引。 UDF 应仅用于(非常)小的集合或与使用集合索引的条件结合使用。
DocumentDB 目前缺少解决此问题的好方法。我建议对以下项目进行投票:
https://feedback.azure.com/forums/263030-documentdb/suggestions/14829654-support-sub-query-functions-like-exists-not-exist
请注意,这是一种工作正常的解决方法。
SELECT c.id FROM c JOIN a in c.companies where a.id = '{id}'
在 Linq 中,这将是
x => x.companies.Any(z => z.id == id)
最初查看 API 时不确定此功能是否可用,但 ARRAY_CONTAINS 现在在末尾支持可选的布尔值以提供部分匹配支持。
SELECT root
FROM root
WHERE ARRAY_CONTAINS(root.servings, { "description": "bar" }, true)
这里是使用 documentdb demo site 查询数组的示例,该数组包含每个存储对象的多个字段。
SELECT *
FROM food as f
WHERE ARRAY_CONTAINS(f.servings, {"description":"bar"}, true)
我正在玩 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
}
]
}
我对 ARRAY_CONTAINS()
感到困惑。此查询 returns 结果:
SELECT root
FROM root
WHERE ARRAY_CONTAINS(root.tags, { "name": "snacks" })
但是,这个查询没有:
SELECT root
FROM root
WHERE ARRAY_CONTAINS(root.servings, { "description": "bar" })
什么给了?
如果这是 C#,我将如何编写查询来说明我想要实现的目标:
var filteredDocs = docs.Where(d => d.Servings != null &&
d.Servings.Length > 0 &&
d.Servings.Any(s => s.Description == "bar"));
root.tags
上的第一个示例查询似乎有效,因为 { "name": "snacks" }
是 root.tags
数组中的 整个 对象,而在第二个查询,{ "description": "bar" }
只是 root.servings
对象中的 一个字段 。
如何修改 root.servings
上的第二个查询,使其只知道服务 description
?
编辑:ARRAY_CONTAINS 现在支持部分匹配,正如 Jim Scott 在下面指出的那样,我认为这是比这个公认的更好的答案。
你servings
数组只有一个条目{"amount": 1, "description": "bar", "weightInGrams": 21}
。
这应该适用于您的单份服务示例:
SELECT root
FROM root
WHERE root.servings[0].description = "bar"
但听起来这不是您要查找的内容。所以,假设你有这个:
{
...
"servings": [
{"description": "baz", ....},
{"description": "bar", ....},
{"description": "bejeweled", ....}
],
...
}
并且您想查找其中一份服务具有描述 "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;
}
使用此查询:
SELECT * FROM c WHERE udf.findServingsByDescription(c.servings, "bar")
如 Larry Maccherone 所述,使用 UDF 的缺点是它不使用集合的索引。 UDF 应仅用于(非常)小的集合或与使用集合索引的条件结合使用。
DocumentDB 目前缺少解决此问题的好方法。我建议对以下项目进行投票: https://feedback.azure.com/forums/263030-documentdb/suggestions/14829654-support-sub-query-functions-like-exists-not-exist
请注意,这是一种工作正常的解决方法。
SELECT c.id FROM c JOIN a in c.companies where a.id = '{id}'
在 Linq 中,这将是
x => x.companies.Any(z => z.id == id)
最初查看 API 时不确定此功能是否可用,但 ARRAY_CONTAINS 现在在末尾支持可选的布尔值以提供部分匹配支持。
SELECT root
FROM root
WHERE ARRAY_CONTAINS(root.servings, { "description": "bar" }, true)
这里是使用 documentdb demo site 查询数组的示例,该数组包含每个存储对象的多个字段。
SELECT *
FROM food as f
WHERE ARRAY_CONTAINS(f.servings, {"description":"bar"}, true)