使用数组的 DocumentDB 查询

DocumentDB queries with arrays

我有包含简单(字符串)数组的文档 属性。

{
     "id": "one",
     "tags": ["A", "B"]
}

{
     "id": "two",
     "tags": ["A", "C"]
}

要检查某个值是否是数组的一部分,我可以使用 ARRAY_CONTAINS

SELECT * FROM c WHERE ARRAY_CONTAINS(c.tags, "B")

将 return 文档 "one"。

如何查询包含数组中可能值列表的文档?

Return 标签数组中至少有一个值为 IN("B", "C").
的所有文档 -> 文档 "one" 和 "two"

您可以将 JOIN 运算符与 IN 运算符结合使用,该运算符用于与嵌套数组元素形成叉积。

SELECT docs
FROM docs
JOIN tags IN docs.tags
WHERE tags IN ("B", "C")

请注意,由于您创建的是叉积,因此您将获得每个匹配子元素的结果,而不是每个文档的结果。

或者,您可以将多个 ARRAY_CONTAINSOR 运算符结合起来,或者编写一个 UDF。

我已经设法通过 Andrew Liu 建议的用户定义函数找到了解决方案,因为 - 正如他提到的 - 这种 JOIN 方法返回叉积,因此每个匹配项都会作为结果给出。

在我的例子中,我需要确定用户是否有权查看文档 - 它是通过组分配到达的。每个用户都有他的组列表,每个文档都有一个允许查看其内容的组列表。

对于所描述的示例,假设我们有一个允许分组 ["g1"、"g2"、"g3"] 的文档和一个可以在分组 [[=] 中查看文档的用户30=],"g3"].

使用我们的SQL JOIN 方法,当我们查找可用文档时,上述文档将被返回两次。如果 Distinct 函数可用于 DocumentDB,也许我不会关心这个,但目前它不是(但你仍然可以 vote 它)。

UDF 是使用 javascript 定义的,因此负责确定两个列表(数组)是否具有公共元素的代码如下所示:

function(array1, array2) {
   return array1.some(function (v) {
       return array2.indexOf(v) >= 0;
   });
}

要从 C# 代码定义此类脚本,您可以遵循以下代码段:

UserDefinedFunction udf =
            _client.CreateUserDefinedFunctionQuery(_collection.UserDefinedFunctionsLink)
                .Where(x => x.Id == "ArraysHasCommonElem")
                .AsEnumerable()
                .FirstOrDefault();

        if (udf == null)
        {
            udf = new UserDefinedFunction
            {
                Body = @"function(array1, array2) {
                            return array1.some(function (v) {
                                return array2.indexOf(v) >= 0;
                            });
                        }",
                Id = "ArraysHasCommonElem"
            };
            await _client.CreateUserDefinedFunctionAsync(collectionUri.SelfLink, udf);
}

最后 运行 工作 SQL 查询记住每个用户定义函数调用之前需要的 'udf' 前缀:

SELECT * FROM docs 
WHERE udf.ArraysHasCommonElem(your_array1, your_array2)