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.
Nota
Se recomienda usar la versión más reciente del SDK de .NET (Microsoft.Azure.Cosmos
).
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
yTruncate
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
yTrimStart
en las funciones de cadena integradas equivalentes. - Funciones de matriz: Admite la traducción desde .NET
Concat
,Contains
yCount
en las funciones integradas de SQL equivalentes. - Funciones de extensión geoespacial: Admite la traducción desde los métodos
Distance
,IsValid
,IsValidDetailed
yWithin
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 de
Coalesce
y los operadores condicionales. Puede traducirContains
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