Поделиться через


Перевод LINQ to NoSQL в Azure Cosmos DB для NoSQL

ОБЛАСТЬ ПРИМЕНЕНИЯ: NoSQL

Поставщик запросов Azure Cosmos DB выполняет сопоставление лучших усилий из запроса LINQ в запрос Azure Cosmos DB для NoSQL. Если вы хотите получить запрос NoSQL, переведенный из LINQ, используйте ToString() метод в созданном IQueryable объекте. В следующем описании предполагается, что вы уже имеете представление о LINQ. Помимо LINQ, Azure Cosmos DB также поддерживает Entity Framework Core, которая работает с API для NoSQL.

Примечание.

Мы рекомендуем использовать последнюю версию пакета SDK для .NET (Microsoft.Azure.Cosmos)

Система типов поставщика запросов поддерживает только примитивные типы JSON: numeric, , Booleanstringи null.

Поставщик запросов поддерживает следующие скалярные выражения:

  • Константы, в том числе значения примитивных типов данных в период оценки запроса.

  • Выражения индексов для свойств и массивов, которые обозначают свойство объекта или элемент массива. Например:

    family.Id;
    family.children[0].familyName;
    family.children[0].grade;
    
    int n = 1;
    
    family.children[n].grade;
    
  • Арифметические выражения, включая стандартные арифметические выражения по численным и логическим значениям.

    2 * family.children[0].grade;
    x + y;
    
  • Выражения сравнения строк, в том числе сравнения строкового значения со строковой константой.

    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);
    
  • Выражения создания объекта или массива, которые возвращают объект или массив объектов комбинированного или анонимного типа. Допускаются вложенные значения.

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

Использование LINQ

Запрос LINQ можно создать с помощью GetItemLinqQueryable. В этом примере демонстрируется создание и асинхронное выполнение запроса LINQ с помощью 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);
    }
}

Поддерживаемые операторы LINQ

Поставщик LINQ, включенный в пакет SDK noSQL .NET, поддерживает следующие операторы:

  • Select: проекции преобразуются в SELECT, включая создание объектов.
  • Где: фильтры преобразуют в WHERE и поддерживают перевод между &&, ||а также ! операторами NoSQL
  • SelectMany: позволяет развертывать массивы в предложение JOIN. Используйте его, чтобы сцеплять или вкладывать выражения для фильтрации по элементам массива.
  • OrderBy и OrderByDescending: преобразуются в ORDER BY с модификатором ASC или DESC.
  • Операторы для агрегирования Count, Sum, Min, Max, Average и их асинхронные эквиваленты CountAsync, SumAsync, MinAsync, MaxAsync и AverageAsync.
  • CompareTo: выполняет преобразование в сравнение диапазонов. Этот оператор обычно используется для строк, так как они не сопоставимы в .NET.
  • Skip и Take: преобразуются в OFFSET и LIMIT для ограничения числа результатов запроса и организации разбиения на страницы.
  • Математические функции: поддерживается преобразование из операторов .NET Abs, Acos, Asin, Atan, Ceiling, Cos, Exp, Floor, Log, Log10, Pow, Round, Sign, Sin, Sqrt, Tan и Truncate в эквивалентные встроенные математические функции.
  • Строковые функции: поддерживается преобразование из операторов .NET Concat, Contains, Count, EndsWith, IndexOf, Replace, Reverse, StartsWith, SubString, ToLower, ToUpper, TrimEnd и TrimStart в эквивалентные встроенные строковые функции.
  • Функции массивов: поддерживается преобразование из операторов .NET Concat, Contains и Count в эквивалентные встроенные функции массивов.
  • Функции геопространственного расширения: поддерживается преобразование из методов-заглушек Distance, IsValid, IsValidDetailed и Within в эквивалентные встроенные геопространственные функции.
  • Функция расширения определяемой пользователем функции: поддерживает перевод из метода заглушки CosmosLinq.InvokeDefinedFunction в соответствующую определяемую пользователем функцию.
  • Прочее: поддерживается преобразование Coalesce и условные операторы. Позволяет преобразовать Contains в CONTAINS, ARRAY_CONTAINS или IN (в зависимости от контекста) со строковым значением.

Примеры

В следующих примерах показано, как некоторые из стандартных операторов запросов LINQ преобразуются в запросы Azure Cosmos DB.

Выбрать оператор

Синтаксис: input.Select(x => f(x)), где f — скалярное выражение. В данном случае input является объектом IQueryable.

Оператор SELECT, пример 1:

  • Лямбда-выражение LINQ

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

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

Оператор SELECT, пример 2:

  • Лямбда-выражение 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
    

Оператор SELECT, пример 3:

  • Лямбда-выражение 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
    

Оператор SelectMany

Синтаксис: input.SelectMany(x => f(x)), где f — скалярное выражение, возвращающее тип контейнера.

  • Лямбда-выражение LINQ

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

    SELECT VALUE child
    FROM child IN Families.children
    

Оператор Where

Синтаксис: input.Where(x => f(x)), где f — скалярное выражение, возвращающее логическое значение.

Оператор WHERE, пример 1:

  • Лямбда-выражение LINQ

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

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

Оператор WHERE, пример 2:

  • Лямбда-выражение 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
    

Составные запросы NoSQL

Вы можете объединять описанные выше операторы для создания более мощных запросов. Так как Azure Cosmos DB поддерживает вложенные контейнеры, вы можете объединить или вложить композицию.

Объединение

Синтаксис: input(.|.SelectMany())(.Select()|.Where())*. Объединенный запрос может начинаться с необязательного запроса SelectMany, за которым идет несколько операторов Select или Where.

Объединение, пример 1:

  • Лямбда-выражение LINQ

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

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

Объединение, пример 2:

  • Лямбда-выражение 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
    

Объединение, пример 3:

  • Лямбда-выражение 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)
    

Объединение, пример 4:

  • Лямбда-выражение LINQ

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

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

Вложенные операторы

Используется синтаксис input.SelectMany(x=>x.Q()), где Q является оператором Select, SelectMany или Where.

Вложенный запрос применяет внутренний запрос к каждому элементу внешнего контейнера. Одной из важных особенностей является то, что внутренний запрос может ссылаться на поля элементов во внешнем контейнере, как при самосоединении.

Вложенность, пример 1:

  • Лямбда-выражение LINQ

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

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

Вложенность, пример 2:

  • Лямбда-выражение 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"
    

Вложенность, пример 3:

  • Лямбда-выражение 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