Partager via


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 et Truncate 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 et TrimStart vers les fonctions de chaîne intégrées équivalentes.
  • Fonctions de tableau : prennent en charge la traduction des fonctions .NET Concat, Contains et Count 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 et Within 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 traduire Contains 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