DocumentDB queries with arrays DocumentDB queries with arrays sql sql

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)