DocumentDB queries with arrays
You can combine the JOIN
operator , which is used to form cross products with nested array elements, with the IN
operator.
SELECT docsFROM docsJOIN tags IN docs.tagsWHERE tags IN ("B", "C")
Note that because you are creating a cross product, that you will get a result for each matching child element, rather than for each document.
Alternatively you could combine several ARRAY_CONTAINS
with OR
operators, or write a UDF.
I've managed to reach solution with User Defined Functions suggested by Andrew Liu, because - as he mentioned - this JOIN
approach is returning cross product, so every single match is given as a result.
In my case I needed to determine if a user is authorized to see the document - it is reached by group assignment. Each user has list of his groups and each document has a list of groups allowed to view its content.
For described example, imagine that we have a document which has allowed groups ["g1","g2","g3"] and a user which can view documents in groups ["g1","g3"].
With usage of our SQL JOIN
method, when we will look for available documents, document described above will be returned twice. Maybe I wouldn't have cared about this if the Distinct function would be available for DocumentDB, but currently it is not (but you can still vote for it).
UDF are defined by using javascript so the code responsible for determining if two lists (arrays) have common element could look like below:
function(array1, array2) { return array1.some(function (v) { return array2.indexOf(v) >= 0; });}
To define such script from C# code you can follow this snippet:
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);}
Finally to run working SQL query remeber about 'udf' prefix required before every User Defined Function call:
SELECT * FROM docs WHERE udf.ArraysHasCommonElem(your_array1, your_array2)