DocumentDB SQL - Tradução de Linq para SQL

No DocumentDB, na verdade usamos SQL para consultar documentos. Se estivermos fazendo desenvolvimento .NET, também haverá um provedor LINQ que pode ser usado e que pode gerar SQL apropriado a partir de uma consulta LINQ.

Tipos de dados suportados

No DocumentDB, todos os tipos primitivos JSON são suportados no provedor LINQ incluído no DocumentDB .NET SDK, que são os seguintes -

  • Numeric
  • Boolean
  • String
  • Null

Expressão Suportada

As seguintes expressões escalares são suportadas no provedor LINQ incluído no DocumentDB .NET SDK.

  • Constant Values - Inclui valores constantes dos tipos de dados primitivos.

  • Property/Array Index Expressions - As expressões referem-se à propriedade de um objeto ou elemento de matriz.

  • Arithmetic Expressions - Inclui expressões aritméticas comuns em valores numéricos e booleanos.

  • String Comparison Expression - Inclui a comparação de um valor de string com algum valor de string constante.

  • Object/Array Creation Expression- Retorna um objeto do tipo de valor composto ou tipo anônimo ou uma matriz de tais objetos. Esses valores podem ser aninhados.

Operadores LINQ com suporte

Aqui está uma lista de operadores LINQ com suporte no provedor LINQ incluído no DocumentDB .NET SDK.

  • Select - As projeções são convertidas em SQL SELECT, incluindo a construção de objetos.

  • Where- Os filtros são traduzidos para SQL WHERE e oferecem suporte à tradução entre &&, || e! para os operadores SQL.

  • SelectMany- Permite a reversão de matrizes para a cláusula SQL JOIN. Pode ser usado para encadear / aninhar expressões para filtrar elementos da matriz.

  • OrderBy and OrderByDescending - Traduz para ORDER BY ascendente / descendente.

  • CompareTo- Traduz em comparações de intervalo. Normalmente usado para strings, uma vez que não são comparáveis ​​no .NET.

  • Take - Traduz para o SQL TOP para limitar os resultados de uma consulta.

  • Math Functions - Suporta tradução de Abs, Acos, Asin, Atan, Ceiling, Cos, Exp, Floor, Log, Log10, Pow, Round, Sign, Sin, Sqrt, Tan, Truncate para as funções embutidas SQL equivalentes.

  • String Functions - Suporta tradução de Concat, Contains, EndsWith, IndexOf, Count, ToLower, TrimStart, Replace, Reverse, TrimEnd, StartsWith, SubString, ToUpper do .NET para as funções integradas SQL equivalentes.

  • Array Functions - Suporta tradução de Concat, Contains e Count do .NET para as funções integradas SQL equivalentes.

  • Geospatial Extension Functions - Suporta tradução de métodos stub Distance, Within, IsValid e IsValidDetailed para as funções integradas SQL equivalentes.

  • User-Defined Extension Function - Suporta tradução do método stub UserDefinedFunctionProvider.Invoke para a função definida pelo usuário correspondente.

  • Miscellaneous- Suporta tradução de operadores condicionais e de coalescência. Pode traduzir Contains para String CONTAINS, ARRAY_CONTAINS ou SQL IN dependendo do contexto.

Vamos dar uma olhada em um exemplo em que usaremos o .Net SDK. A seguir estão os três documentos que consideraremos para este exemplo.

Novo 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" 
   }, 
}

Novo Cliente 2

{ 
   "name": "New Customer 2", 
	
   "address": {
      "addressType": "Main Office", 
      "addressLine1": "678 Main Street", 
		
      "location": { 
         "city": "London", 
         "stateProvinceName": " London " 
      }, 
	  
      "postalCode": "11229", 
      "countryRegionName": "United Kingdom" 
   }, 
}

Novo 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 seguir está o código em que consultamos usando LINQ. Definimos uma consulta LINQ emq, mas não será executado até executarmos .ToList nele.

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(); 
}

O SDK converterá nossa consulta LINQ em sintaxe SQL para DocumentDB, gerando uma cláusula SELECT e WHERE com base em nossa sintaxe LINQ.

Vamos chamar as consultas acima da tarefa 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); 
   } 
}

Quando o código acima é executado, ele produz a seguinte saída.

**** 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