Share via


Traducción de LINQ a NoSQL en Azure Cosmos DB for NoSQL

SE APLICA A: NoSQL

El proveedor de consulta de Azure Cosmos DB realiza un mejor trabajo de asignación desde una consulta de LINQ a una consulta de Azure Cosmos DB for NoSQL. Si quiere obtener la consulta NoSQL traducida de LINQ, use el método ToString() en el objeto IQueryable generado. En la descripción siguiente se da por supuesto un conocimiento básico de LINQ. Además de LINQ, Azure Cosmos DB también admite Entity Framework Core que funciona con la API para NoSQL.

El sistema de tipos del proveedor de consultas admite solo los tipos primitivos de JSON: numeric, Boolean, string y null.

El proveedor de consultas admite las siguientes expresiones escalares:

  • Valores constantes, incluidos los de los tipos de datos primitivos durante la evaluación de la consulta.

  • Expresiones de índice de propiedad o matriz que hacen referencia a la propiedad de un objeto o a un elemento de matriz. Por ejemplo:

    family.Id;
    family.children[0].familyName;
    family.children[0].grade;
    
    int n = 1;
    
    family.children[n].grade;
    
  • Expresiones aritméticas, incluidas las expresiones aritméticas comunes con valores numéricos y booleanos.

    2 * family.children[0].grade;
    x + y;
    
  • Expresiones de comparación de cadenas, que incluyen la comparación de un valor de cadena con algún valor de cadena constante.

    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);
    
  • Expresiones de creación de objetos o matrices, que devuelven un objeto de tipo de valor compuesto o tipo anónimo, o una matriz de estos objetos. Puede anidar estos valores.

    new Parent { familyName = "Wakefield", givenName = "Robin" };
    new { first = 1, second = 2 }; //an anonymous type with two fields  
    new int[] { 3, child.grade, 5 };
    

Uso de LINQ

Puede crear una consulta de LINQ con GetItemLinqQueryable. En este ejemplo se muestra la generación de una consulta de LINQ y su ejecución asincrónica con un elemento 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);
    }
}

Operadores de LINQ admitidos

El proveedor LINQ incluido con el SDK de .NET para NoSQL admite los operadores siguientes:

  • Select: las proyecciones se traducen a la instrucción SELECT, incluida la construcción de objetos.
  • Where: los filtros se traducen a WHERE, admiten la traducción entre &&, ||, y ! a los operadores NoSQL
  • SelectMany: permite desenredar las matrices a la cláusula JOIN. Úselo para encadenar o anidar expresiones para filtrar los elementos de la matriz.
  • OrderBy y OrderByDescending: se traducen a ORDER BY con ASC o DESC.
  • Los operadores Count, Sum, Min, Max y Average para la agregación y sus equivalentes asincrónicos CountAsync, SumAsync, MinAsync, MaxAsync y AverageAsync.
  • CompareTo: Se traduce a las comparaciones de intervalos. Este operador se usa frecuentemente en las cadenas, ya que no es comparable en .NET.
  • Skip y Take: se traducen en OFFSET y LIMIT para limitar los resultados de una consulta y realizar la paginación.
  • Funciones matemáticas: Admite la traducción de .NET Abs, Acos, Asin, Atan, Ceiling, Cos, Exp, Floor, Log, Log10, Pow, Round, Sign, Sin, Sqrt, Tan y Truncate en las funciones matemáticas integradas equivalentes.
  • Funciones de cadena: Admite la conversión de .NET Concat, Contains, Count, EndsWith,IndexOf, Replace, Reverse, StartsWith, SubString, ToLower, ToUpper, TrimEnd y TrimStart en las funciones de cadena integradas equivalentes.
  • Funciones de matriz: Admite la traducción desde .NET Concat, Contains y Count en las funciones integradas de SQL equivalentes.
  • Funciones de extensión geoespacial: Admite la traducción desde los métodos Distance, IsValid, IsValidDetailed y Within de stub en las funciones geoespaciales integradas equivalentes.
  • Función de extensión de función definida por el usuario: admite la traducción del método de código auxiliar CosmosLinq.InvokeUserDefinedFunction a la correspondiente función definida por el usuario.
  • Varios: Admite la traducción deCoalesce y los operadores condicionales. Puede traducir Contains a la cadena CONTAINS, ARRAY_CONTAINS o IN, según el contexto.

Ejemplos

Los ejemplos siguientes ilustran la traducción de algunos de los operadores de consulta de LINQ estándar a las consultas de Azure Cosmos DB.

Operador Select

La sintaxis es input.Select(x => f(x)), donde f es una expresión escalar. En este caso, el valor input sería un objeto IQueryable.

Operador Select, ejemplo 1:

  • Expresión lambda de LINQ

    input.Select(family => family.parents[0].familyName);
    
  • NoSQL

    SELECT VALUE f.parents[0].familyName
    FROM Families f
    

Operador Select, ejemplo 2:

  • Expresión lambda de 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
    

Operador Select, ejemplo 3:

  • Expresión lambda de 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
    

Operador SelectMany

La sintaxis es input.SelectMany(x => f(x)), donde f es una expresión escalar que devuelve un tipo de contenedor.

  • Expresión lambda de LINQ

    input.SelectMany(family => family.children);
    
  • NoSQL

    SELECT VALUE child
    FROM child IN Families.children
    

Operador Where

La sintaxis es input.Where(x => f(x)), donde f es una expresión escalar que devuelve un valor booleano.

Operador Where, ejemplo 1:

  • Expresión lambda de LINQ

    input.Where(family=> family.parents[0].familyName == "Wakefield");
    
  • NoSQL

    SELECT *
    FROM Families f
    WHERE f.parents[0].familyName = "Wakefield"
    

Operador Where, ejemplo 2:

  • Expresión lambda de 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
    

Consultas NoSQL compuestas

Puede componer los operadores anteriores para formar consultas más eficaces. Dado que Azure Cosmos DB admite contenedores anidados, puede concatenar o anidar la composición.

Concatenación

La sintaxis es input(.|.SelectMany())(.Select()|.Where())*. Una consulta concatenada puede empezar por una consulta SelectMany opcional, seguida de varios operadores Select o Where.

Concatenación, ejemplo 1:

  • Expresión lambda de LINQ

    input.Select(family => family.parents[0])
        .Where(parent => parent.familyName == "Wakefield");
    
  • NoSQL

    SELECT *
    FROM Families f
    WHERE f.parents[0].familyName = "Wakefield"
    

Concatenación, ejemplo 2:

  • Expresión lambda de 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
    

Concatenación, ejemplo 3:

  • Expresión lambda de 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)
    

Concatenación, ejemplo 4:

  • Expresión lambda de LINQ

    input.SelectMany(family => family.parents)
        .Where(parent => parents.familyName == "Wakefield");
    
  • NoSQL

    SELECT *
    FROM p IN Families.parents
    WHERE p.familyName = "Wakefield"
    

Anidamiento

La sintaxis es input.SelectMany(x=>x.Q()), donde Q es un operador Select, SelectMany o Where.

Una consulta anidada aplica la consulta interna a cada elemento del contenedor externo. Una característica importante es que la consulta interna puede hacer referencia a los campos de los elementos del contenedor externo, como una autocombinación.

Anidamiento, ejemplo 1:

  • Expresión lambda de LINQ

    input.SelectMany(family=>
        family.parents.Select(p => p.familyName));
    
  • NoSQL

    SELECT VALUE p.familyName
    FROM Families f
    JOIN p IN f.parents
    

Anidamiento, ejemplo 2:

  • Expresión lambda de 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"
    

Anidamiento, ejemplo 3:

  • Expresión lambda de 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