Перевод LINQ — язык запросов в Cosmos DB (в Azure и Fabric)

Поставщик запросов Cosmos DB (в Azure и Fabric) преобразует интегрированные с языком запросы (LINQ) в запросы NoSQL для эффективного получения данных. В этой статье объясняется, какие операторы LINQ поддерживаются и как LINQ-запросы сопоставляются с синтаксисом Cosmos DB, помогая разработчикам .NET оптимизировать запросы к базе данных. Чтобы просмотреть переведенный запрос NoSQL из кода LINQ, используйте ToString() метод в созданном IQueryable объекте. В следующем описании предполагается базовое знакомство с LINQ. Помимо LINQ, 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();

//Asynchronous query execution
while (setIterator.HasMoreResults)
{
    foreach (var item in await setIterator.ReadNextAsync())
    {
        Console.WriteLine(item.Cost);
    }
}

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

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

  • Выберите: проекции преобразуют SELECTв , включая строительство объектов.
  • Где: фильтры преобразовывается WHEREв операторы NoSQL и поддерживает перевод между &&ними ||и ! в операторы NoSQL.
  • SelectMany: разрешает очистку массивов в предложении JOIN . Используется для цепочки или вложенных выражений для фильтрации по элементам массива.
  • OrderBy и OrderByDescending: перевод с ORDER BYASC помощью или DESC.
  • Операторы Count, Sum, Min, Max и Average для агрегирования и их асинхронные эквиваленты CountAsync, SumAsync, MinAsync, MaxAsync и AverageAsync.
  • CompareTo: преобразуется в сравнения диапазонов. Этот оператор обычно используется для строк, так как строки не поддерживают < и > операторы сравнения непосредственно в .NET.
  • Пропустить и принять: преобразует OFFSETLIMIT и ограничивает результаты запроса и выполняет разбиение на страницы.
  • Математические функции: поддерживает перевод из .NETAbs, AcosAsinAtanCeilingCosExpFloorLogLog10PowRoundSignSinSqrtTanи Truncate эквивалентных встроенных математических функций.
  • Строковые функции: поддерживает перевод из .NETConcat, ContainsCountEndsWithIndexOfReplaceReverseStartsWithSubstringToLowerToUpperTrimEndи TrimStart эквивалентных встроенных строковых функций.
  • Функции массива: поддерживает преобразование из .NET Concatи ContainsCountэквивалентные встроенные функции массива.
  • Функции геопространственного расширения: поддерживает перевод из методов Distanceзаглушки, IsValidIsValidDetailedи Withinэквивалентных встроенных геопространственных функций.
  • функция расширения функцииUser-Defined: поддерживает перевод из метода CosmosLinq.InvokeUserDefinedFunction заглушки в соответствующую определяемую пользователем функцию.
  • Прочее: поддерживает перевод и условные Coalesceоператоры. Может преобразовывать Contains строку в CONTAINSстроковый ARRAY_CONTAINSили INв зависимости от контекста.

Примеры

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

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

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

Выберите оператор, пример 1:

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

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

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

Выберите оператор, пример 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
    

Выберите оператор, пример 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 Families f
    JOIN child IN f.children
    

Оператор Where

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

Где оператор, пример 1:

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

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

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

Где оператор, пример 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

Вы можете создать предыдущие операторы, чтобы сформировать более мощные запросы. Так как 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 => parent.familyName == "Wakefield");
    
  • NoSQL

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

Вложенность

Синтаксис находится input.SelectMany(x=>x.Q()) в том месте, где QSelectнаходится оператор , 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