DocumentDB SQL - Traducción de Linq a SQL
En DocumentDB, en realidad usamos SQL para consultar documentos. Si estamos desarrollando .NET, también hay un proveedor LINQ que se puede utilizar y que puede generar SQL apropiado a partir de una consulta LINQ.
Tipos de datos admitidos
En DocumentDB, todos los tipos primitivos JSON son compatibles con el proveedor LINQ incluido con DocumentDB .NET SDK, que son los siguientes:
- Numeric
- Boolean
- String
- Null
Expresión admitida
Las siguientes expresiones escalares son compatibles con el proveedor LINQ incluido con DocumentDB .NET SDK.
Constant Values - Incluye valores constantes de los tipos de datos primitivos.
Property/Array Index Expressions - Las expresiones se refieren a la propiedad de un objeto o un elemento de matriz.
Arithmetic Expressions - Incluye expresiones aritméticas comunes en valores numéricos y booleanos.
String Comparison Expression - Incluye comparar un valor de cadena con algún valor de cadena constante.
Object/Array Creation Expression- Devuelve un objeto de tipo de valor compuesto o de tipo anónimo o una matriz de dichos objetos. Estos valores se pueden anidar.
Operadores LINQ compatibles
A continuación se muestra una lista de los operadores LINQ admitidos en el proveedor LINQ incluido con el SDK de DocumentDB .NET.
Select - Las proyecciones se traducen en SQL SELECT, incluida la construcción de objetos.
Where- Los filtros se traducen al SQL WHERE y admiten la traducción entre &&, || y! a los operadores SQL.
SelectMany- Permite desenrollar matrices en la cláusula SQL JOIN. Se puede usar para encadenar / anidar expresiones para filtrar elementos de matriz.
OrderBy and OrderByDescending - Se traduce como ORDER BY ascendente / descendente.
CompareTo- Se traduce en comparaciones de rango. Se usa comúnmente para cadenas, ya que no son comparables en .NET.
Take - Se traduce al SQL TOP para limitar los resultados de una consulta.
Math Functions - Admite la traducción de Abs, Acos, Asin, Atan, Ceiling, Cos, Exp, Floor, Log, Log10, Pow, Round, Sign, Sin, Sqrt, Tan, Truncate de .NET a las funciones integradas SQL equivalentes.
String Functions - Admite la traducción de Concat, Contains, EndsWith, IndexOf, Count, ToLower, TrimStart, Replace, Reverse, TrimEnd, StartsWith, SubString, ToUpper de .NET a las funciones integradas SQL equivalentes.
Array Functions - Admite la traducción de Concat, Contains y Count de .NET a las funciones integradas de SQL equivalentes.
Geospatial Extension Functions - Admite la traducción de los métodos de código auxiliar Distance, Within, IsValid e IsValidDetailed a las funciones integradas de SQL equivalentes.
User-Defined Extension Function - Admite la traducción del método de código auxiliar UserDefinedFunctionProvider.Invoke a la función definida por el usuario correspondiente.
Miscellaneous- Admite la traducción de operadores coalescentes y condicionales. Puede traducir Contains a String CONTAINS, ARRAY_CONTAINS o SQL IN según el contexto.
Echemos un vistazo a un ejemplo en el que utilizaremos .Net SDK. A continuación se muestran los tres documentos que consideraremos para este ejemplo.
Nuevo cliente 1
{
"name": "New Customer 1",
"address": {
"addressType": "Main Office",
"addressLine1": "123 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
}
Nuevo cliente 2
{
"name": "New Customer 2",
"address": {
"addressType": "Main Office",
"addressLine1": "678 Main Street",
"location": {
"city": "London",
"stateProvinceName": " London "
},
"postalCode": "11229",
"countryRegionName": "United Kingdom"
},
}
Nuevo cliente 3
{
"name": "New Customer 3",
"address": {
"addressType": "Main Office",
"addressLine1": "12 Main Street",
"location": {
"city": "Brooklyn",
"stateProvinceName": "New York"
},
"postalCode": "11229",
"countryRegionName": "United States"
},
}
A continuación se muestra el código en el que consultamos usando LINQ. Hemos definido una consulta LINQ enq, pero no se ejecutará hasta que ejecutemos .ToList en él.
private static void QueryDocumentsWithLinq(DocumentClient client) {
Console.WriteLine();
Console.WriteLine("**** Query Documents (LINQ) ****");
Console.WriteLine();
Console.WriteLine("Quering for US customers (LINQ)");
var q =
from d in client.CreateDocumentQuery<Customer>(collection.DocumentsLink)
where d.Address.CountryRegionName == "United States"
select new {
Id = d.Id,
Name = d.Name,
City = d.Address.Location.City
};
var documents = q.ToList();
Console.WriteLine("Found {0} US customers", documents.Count);
foreach (var document in documents) {
var d = document as dynamic;
Console.WriteLine(" Id: {0}; Name: {1}; City: {2}", d.Id, d.Name, d.City);
}
Console.WriteLine();
}
El SDK convertirá nuestra consulta LINQ en sintaxis SQL para DocumentDB, generando una cláusula SELECT y WHERE basada en nuestra sintaxis LINQ.
Llamemos a las consultas anteriores desde la tarea CreateDocumentClient.
private static async Task CreateDocumentClient() {
// Create a new instance of the DocumentClient
using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) {
database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id =
'myfirstdb'").AsEnumerable().First();
collection = client.CreateDocumentCollectionQuery(database.CollectionsLink,
"SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();
QueryDocumentsWithLinq(client);
}
}
Cuando se ejecuta el código anterior, produce la siguiente salida.
**** Query Documents (LINQ) ****
Quering for US customers (LINQ)
Found 2 US customers
Id: 7e9ad4fa-c432-4d1a-b120-58fd7113609f; Name: New Customer 1; City: Brooklyn
Id: 34e9873a-94c8-4720-9146-d63fb7840fad; Name: New Customer 1; City: Brooklyn