/// <summary> /// Visits a SqlAliasedCollectionExpression and transforms the documents accordingly. /// </summary> /// <param name="collectionExpression">The collection expression to visit.</param> /// <param name="documents">The documents to transform.</param> /// <returns>The transformed documents according to the collection expression.</returns> public override IEnumerable <CosmosElement> Visit(SqlAliasedCollectionExpression collectionExpression, IEnumerable <CosmosElement> documents) { //If the query was: //SELECT * //FROM c //and the document was: //{ // "name" : "John" //} //Then this function would return: //{ // "c" : { "name" : "John" } //} //which is just wrapping the original document in the identifier. // Get the sub collection CollectionEvaluationResult collectionEvaluationResult = collectionExpression.Collection.Accept( SqlInterpreterCollectionVisitor.Singleton, documents); string identifer = collectionEvaluationResult.Identifer; // Figure out what the alias should be int aliasCounter = 0; string alias; if (collectionExpression.Alias != null) { alias = collectionExpression.Alias.Value; } else if (identifer != null) { alias = identifer; } else { alias = $"#{aliasCounter++}"; } // Wrap the collection in the alias so it's easier to bind later foreach (Tuple <CosmosElement, string> subDocumentAndRid in collectionEvaluationResult.SubDocumentsAndRids) { Dictionary <string, CosmosElement> wrappedDocument = new Dictionary <string, CosmosElement> { [alias] = subDocumentAndRid.Item1, //// Add the _rid so that we can break ties for sort later ["_rid"] = CosmosString.Create(subDocumentAndRid.Item2) }; yield return(CosmosObject.Create(wrappedDocument)); } }
/// <summary> /// Visits a SqlArrayIteratorCollectionExpression and transforms the documents accordingly. /// </summary> /// <param name="collectionExpression">The collection expression to visit.</param> /// <param name="documents">The documents to transform.</param> /// <returns>The transformed documents according to the collection expression.</returns> public override IEnumerable <CosmosElement> Visit(SqlArrayIteratorCollectionExpression collectionExpression, IEnumerable <CosmosElement> documents) { //If the query was: //SELECT p //FROM p in c.parents //and the document was //{ // "parents" : [{"name" : "John"}, {"name" : "Sally"}] //} //then the results would be: //{ "p" : {"name" : "John"} } //and //{ "p" : {"name" : "Sally"} } //Notice that the result set is larger than the input //This is because we emitted one document for each parent in the original document //and wrapped it in the provided alias. // throw away the identifer since we always have an alias CollectionEvaluationResult collectionEvaluationResult = collectionExpression.Collection.Accept( SqlInterpreterCollectionVisitor.Singleton, documents); // Wrap the collection in the alias so it's easier to bind later foreach (Tuple <CosmosElement, string> subDocumentAndRid in collectionEvaluationResult.SubDocumentsAndRids) { CosmosElement document = subDocumentAndRid.Item1; string rid = subDocumentAndRid.Item2; if (document is CosmosArray array) { foreach (CosmosElement item in array) { Dictionary <string, CosmosElement> wrappedDocument = new Dictionary <string, CosmosElement> { [collectionExpression.Identifier.Value] = item, //// Add the _rid so that we can break ties for sort later ["_rid"] = CosmosString.Create(rid), }; yield return(CosmosObject.Create(wrappedDocument)); } } } }