2015-07-07 7 views
6

Ich habe Dokumente mit einer einfachen (String-) Array-Eigenschaft.DocumentDB Abfragen mit Arrays

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

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

Um zu überprüfen, ob ein Wert Teil eines Arrays ist, ich ARRAY_CONTAINS

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

zurückkehren Dokument "Eins" verwenden könnte.

Wie kann ich nach Dokumenten mit einer Liste möglicher Werte im Array suchen?

Alle Dokumente zurückgeben, in denen mindestens ein Wert des Variablen-Arrays IN ist ("B", "C").
-> Dokumente „eins“ und „zwei“

Antwort

4

Sie den JOIN Operator kombinieren kann, die verwendet wird, Kreuzprodukte mit verschachtelten Array-Elementen zu bilden, mit dem IN Operator.

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

Beachten Sie, dass, weil Sie ein Kreuzprodukt erstellen, dass Sie ein Ergebnis für jedes passende Kind-Element erhalten wird, anstatt für jedes Dokument. Alternativ können Sie mehrere ARRAY_CONTAINS mit OR Operatoren kombinieren oder eine UDF schreiben.

+0

Vielen Dank! Das hat es fast gelöst. Nein * für Join-Abfragen und() anstelle von [] –

+0

Hoppla - die Abfrage wurde korrigiert :) –

1

Ich habe es geschafft, die von Andrew Liu vorgeschlagene Lösung mit benutzerdefinierten Funktionen zu erreichen, weil - wie er bereits erwähnte - dieser JOIN Ansatz das Produkt zurückgibt, so dass jedes einzelne Ergebnis als Ergebnis zurückgegeben wird.

In meinem Fall musste ich feststellen, ob ein Benutzer berechtigt ist, das Dokument zu sehen - es wird durch Gruppenzuweisung erreicht. Jeder Benutzer hat eine Liste seiner Gruppen und jedes Dokument hat eine Liste von Gruppen, die seinen Inhalt sehen dürfen.

Stellen Sie sich vor, dass wir ein Dokument haben, das Gruppen ["g1", "g2", "g3"] und einen Benutzer erlaubt, der Dokumente in Gruppen ["g1", "g3"] anzeigen kann.

Bei Verwendung unserer SQL-Methode JOIN, wenn wir nach verfügbaren Dokumenten suchen, wird das oben beschriebene Dokument zweimal zurückgegeben. Vielleicht hätte ich mich nicht darum gekümmert, wenn die Distinct-Funktion für DocumentDB verfügbar wäre, aber momentan ist es nicht (aber Sie können immer noch vote dafür).

UDF werden unter Verwendung von Javascript, so definiert, dass der Code verantwortlich für die Bestimmung, ob zwei Listen (Arrays) gemeinsames Element haben wie folgt aussehen könnte:

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

so zu definieren, Skript von C# -Code Sie diesem Schnipsel folgen:

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); 
} 

schließlich zu 'UDF' arbeiten SQL-Abfrage remeber laufen Präfix vor jedem User Defined Function Aufruf erforderlich:

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