Traduction de LINQ en NoSQL dans Azure Cosmos DB for NoSQL
S’APPLIQUE À : NoSQL
Le fournisseur de requêtes d’Azure Cosmos DB effectue le meilleur mappage possible entre une requête LINQ et une requête Azure Cosmos DB for NoSQL. Si vous souhaitez obtenir la requête NoSQL traduite à partir de LINQ, utilisez la méthode ToString()
sur l’objet IQueryable
généré. La description suivante suppose une connaissance de base de LINQ. Outre LINQ, Azure Cosmos DB prend également en charge Entity Framework Core qui fonctionne avec l’API pour NoSQL.
Notes
Nous recommandons d’utiliser la dernière version du Kit de développement logiciel (SDK) (Microsoft.Azure.Cosmos
) .NET
Le système de type du fournisseur de requêtes prend en charge uniquement les types primitifs JSON : numeric
, Boolean
, string
et null
.
Le fournisseur de requêtes prend en charge les expressions scalaires suivantes :
Valeurs constantes, y compris les valeurs constantes des types de données primitifs au moment de l’évaluation de la requête.
Expressions d’index de propriété/tableau qui font référence à la propriété d’un objet ou d’un élément de tableau. Par exemple :
family.Id; family.children[0].familyName; family.children[0].grade;
int n = 1; family.children[n].grade;
Expressions arithmétiques, y compris les expressions arithmétiques communes sur les valeurs numériques et booléennes.
2 * family.children[0].grade; x + y;
Expressions de comparaison de chaîne, qui incluent les comparaisons de valeurs de chaînes à certaines valeurs de chaînes constantes.
mother.familyName.StringEquals("Wakefield");
string s = "Rob"; string e = "in"; string c = "obi"; child.givenName.StartsWith(s); child.givenName.EndsWith(e); child.givenName.Contains(c);
Expressions de création d’objet/tableau, qui retournent un objet de type de valeur composée ou de type anonyme ou un tableau de tels objets. Vous pouvez imbriquer ces valeurs.
new Parent { familyName = "Wakefield", givenName = "Robin" }; new { first = 1, second = 2 }; //an anonymous type with two fields new int[] { 3, child.grade, 5 };
Utilisation de LINQ
Vous pouvez créer une requête LINQ à l’aide de GetItemLinqQueryable
. Cet exemple illustre la génération et l’exécution asynchrone de requêtes LINQ avec un FeedIterator
:
using FeedIterator<Book> setIterator = container.GetItemLinqQueryable<Book>()
.Where(b => b.Title == "War and Peace")
.ToFeedIterator<Book>());
//Asynchronous query execution
while (setIterator.HasMoreResults)
{
foreach(var item in await setIterator.ReadNextAsync()){
{
Console.WriteLine(item.cost);
}
}
Opérateurs LINQ pris en charge
Le fournisseur LINQ inclus avec le kit SDK .NET NoSQL prend en charge les opérateurs suivants :
- Select : les projections sont traduites en SELECT, y compris la construction d’objets.
- Where : les filtres sont traduits en WHERE et prennent en charge la traduction de
&&
,||
et!
en opérateurs NoSQL. - SelectMany : autorise le déroulement de tableaux vers la clause JOIN. Permet d’associer/imbriquer des expressions afin de filtrer les éléments de tableau.
- OrderBy et OrderByDescending : sont traduits en ORDER BY avec ASC ou DESC.
- Les opérateurs Count, Sum, Min, Max et Average pour l’agrégation, et leurs équivalents asynchrones CountAsync, SumAsync, MinAsync, MaxAsync et AverageAsync.
- CompareTo : se traduit par des comparaisons de plages. Cet opérateur est généralement utilisé pour des chaînes, car elles ne sont pas comparables dans .NET.
- Skip et Take : traduit en OFFSET et LIMIT afin de limiter les résultats d’une requête et d’effectuer la pagination.
- Fonctions mathématiques : prennent en charge la traduction des fonctions .NET
Abs
,Acos
,Asin
,Atan
,Ceiling
,Cos
,Exp
,Floor
,Log
,Log10
,Pow
,Round
,Sign
,Sin
,Sqrt
,Tan
etTruncate
vers les fonctions mathématiques intégrées équivalentes. - Fonctions de chaîne : prennent en charge la traduction des fonctions .NET
Concat
,Contains
,Count
,EndsWith
,IndexOf
,Replace
,Reverse
,StartsWith
,SubString
,ToLower
,ToUpper
,TrimEnd
etTrimStart
vers les fonctions de chaîne intégrées équivalentes. - Fonctions de tableau : prennent en charge la traduction des fonctions .NET
Concat
,Contains
etCount
vers les fonctions de tableau intégrées équivalentes. - Fonctions d’extension géospatiale : prennent en charge la traduction des méthodes stub
Distance
,IsValid
,IsValidDetailed
etWithin
vers les fonctions géospatiales intégrées équivalentes. - Fonction d'extension de fonction définie par l'utilisateur : prend en charge la traduction de la méthode stub CosmosLinq.InvokeUserDefinedFunction vers la fonction définie par l'utilisateur correspondante.
- Divers : prend en charge la traduction de
Coalesce
et des opérateurs conditionnels. Peut traduireContains
en chaîne CONTAINS, ARRAY_CONTAINS ou IN, selon le contexte.
Exemples
Les exemples suivants illustrent la traduction de certains opérateurs standard de requête LINQ en requêtes dans Azure Cosmos DB.
Opérateur Select
La syntaxe est input.Select(x => f(x))
, où f
est une expression scalaire. Dans ce cas, input
est un objet IQueryable
.
Opérateur Select, exemple 1 :
Expression Lambda LINQ
input.Select(family => family.parents[0].familyName);
NoSQL
SELECT VALUE f.parents[0].familyName FROM Families f
Opérateur Select, exemple 2 :
Expression Lambda LINQ
input.Select(family => family.children[0].grade + c); // c is an int variable
NoSQL
SELECT VALUE f.children[0].grade + c FROM Families f
Opérateur Select, exemple 3 :
Expression Lambda LINQ
input.Select(family => new { name = family.children[0].familyName, grade = family.children[0].grade + 3 });
NoSQL
SELECT VALUE { "name":f.children[0].familyName, "grade": f.children[0].grade + 3 } FROM Families f
Opérateur SelectMany
La syntaxe est input.SelectMany(x => f(x))
, où f
est une expression scalaire qui retourne un type de conteneur.
Expression Lambda LINQ
input.SelectMany(family => family.children);
NoSQL
SELECT VALUE child FROM child IN Families.children
Opérateur Where
La syntaxe est input.Where(x => f(x))
, où f
est une expression scalaire qui retourne une valeur booléenne.
Opérateur Where, exemple 1 :
Expression Lambda LINQ
input.Where(family=> family.parents[0].familyName == "Wakefield");
NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield"
Opérateur Where, exemple 2 :
Expression Lambda LINQ
input.Where( family => family.parents[0].familyName == "Wakefield" && family.children[0].grade < 3);
NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield" AND f.children[0].grade < 3
Requêtes NoSQL composées
Vous pouvez composer les opérateurs précédents pour former des requêtes plus puissantes. Étant donné qu’ Azure Cosmos DB prend en charge les conteneurs imbriqués, vous pouvez concaténer ou imbriquer la composition.
Concaténation
La syntaxe est input(.|.SelectMany())(.Select()|.Where())*
. Une requête concaténée peut commencer par une requête SelectMany
facultative, suivie de plusieurs opérateurs Select
ou Where
.
Concaténation, exemple 1 :
Expression Lambda LINQ
input.Select(family => family.parents[0]) .Where(parent => parent.familyName == "Wakefield");
NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield"
Concaténation, exemple 2 :
Expression Lambda LINQ
input.Where(family => family.children[0].grade > 3) .Select(family => family.parents[0].familyName);
NoSQL
SELECT VALUE f.parents[0].familyName FROM Families f WHERE f.children[0].grade > 3
Concaténation, exemple 3 :
Expression Lambda LINQ
input.Select(family => new { grade=family.children[0].grade}). Where(anon=> anon.grade < 3);
NoSQL
SELECT * FROM Families f WHERE ({grade: f.children[0].grade}.grade > 3)
Concaténation, exemple 4 :
Expression Lambda LINQ
input.SelectMany(family => family.parents) .Where(parent => parents.familyName == "Wakefield");
NoSQL
SELECT * FROM p IN Families.parents WHERE p.familyName = "Wakefield"
Imbrication
La syntaxe est input.SelectMany(x=>x.Q())
, où Q
est un opérateur Select
, SelectMany
ou Where
.
Une requête imbriquée applique la requête interne à chaque élément du conteneur externe. Une caractéristique importante est la capacité de la requête interne à faire référence aux champs des éléments du conteneur externe, à l’instar d’une jointure réflexive.
Imbrication, exemple 1 :
Expression Lambda LINQ
input.SelectMany(family=> family.parents.Select(p => p.familyName));
NoSQL
SELECT VALUE p.familyName FROM Families f JOIN p IN f.parents
Imbrication, exemple 2 :
Expression Lambda LINQ
input.SelectMany(family => family.children.Where(child => child.familyName == "Jeff"));
NoSQL
SELECT * FROM Families f JOIN c IN f.children WHERE c.familyName = "Jeff"
Imbrication, exemple 3 :
Expression Lambda LINQ
input.SelectMany(family => family.children.Where( child => child.familyName == family.parents[0].familyName));
NoSQL
SELECT * FROM Families f JOIN c IN f.children WHERE c.familyName = f.parents[0].familyName