DocumentDB SQL mit ARRAY_CONTAINS

Ich spiele auf https://www.documentdb.com/sql/demo herum, was es mir erlaubt, Beispieldokumente abzufragen, die wie folgt aussehen:

{ "id": "19015", "description": "Snacks, granola bars, hard, plain", "tags": [ { "name": "snacks" } ], "version": 1, "isFromSurvey": false, "foodGroup": "Snacks", "servings": [ { "amount": 1, "description": "bar", "weightInGrams": 21 } ] } 

Ich bin verwirrt über ARRAY_CONTAINS() . Diese Abfrage gibt Ergebnisse zurück:

 SELECT root FROM root WHERE ARRAY_CONTAINS(root.tags, { "name": "snacks" }) 

Diese Abfrage führt jedoch nicht:

 SELECT root FROM root WHERE ARRAY_CONTAINS(root.servings, { "description": "bar" }) 

Was gibt?

Was ich versuche zu erreichen, zeigt sich daran, wie ich die Abfrage schreiben würde, wenn dies C # wäre:

 var filteredDocs = docs.Where(d => d.Servings != null && d.Servings.Length > 0 && d.Servings.Any(s => s.Description == "bar")); 

Es scheint, dass die erste Beispielabfrage für root.tags funktioniert, weil { "name": "snacks" } das gesamte object im root.tags , während in der zweiten Abfrage { "description": "bar" } nur steht ein Feld in den root.servings objecten.

Wie kann ich die zweite Abfrage auf root.servings , um nur mit der Serving- description ?

Solutions Collecting From Web of "DocumentDB SQL mit ARRAY_CONTAINS"

Ihr servings array hat nur einen Eintrag {"amount": 1, "description": "bar", "weightInGrams": 21} .

Dies sollte für Ihr Beispiel mit einer einzigen Portion funktionieren:

 SELECT root FROM root WHERE root.servings[0].description = "bar" 

Aber es hört sich so an, als ob Sie nicht danach suchen. Also, vorausgesetzt du hast das:

 { ... "servings": [ {"description": "baz", ....}, {"description": "bar", ....}, {"description": "bejeweled", ....} ], ... } 

Und Sie möchten die Dokumente finden, in denen eine der Portionen die Beschreibung "bar" hat, dann könnten Sie diese UDF verwenden:

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

Mit dieser Abfrage:

 SELECT * FROM c WHERE udf.findServingsByDescription(c.servings, "bar") 

Die Verwendung einer UDF hat, wie Larry Maccherone erwähnt, den Nachteil, dass sie den Index der Sammlung nicht verwendet. Ein UDF sollte nur in (sehr) kleinen collections oder in Kombination mit Kriterien verwendet werden, die den Index der Sammlung verwenden.

Eine gute Lösung für dieses Problem fehlt derzeit in DocumentDB. Ich würde empfehlen, über den folgenden Punkt abzustimmen: https://feedback.azure.com/forums/263030-documentdb/suggestions/14829654-support-sub-query-functions-like-exists-not-exist

Beachten Sie, dass dies eine Problemumgehung ist, die einwandfrei funktioniert.

 SELECT c.id FROM c JOIN a in c.companies where a.id = '{id}' 

In Linq wäre das so

 x => x.companies.Any(z => z.id == id)