LINQ-översättning – Frågespråk i Cosmos DB (i Azure och Fabric)

Cosmos DB-frågeprovidern (i Azure och Fabric) översätter språkintegrerade frågor (LINQ) till NoSQL-frågor för effektiv datahämtning. Den här artikeln förklarar vilka LINQ-operatorer som stöds och hur LINQ-frågor mappas till Cosmos DB-syntax, vilket hjälper .NET-utvecklare att optimera sina databasfrågor. Om du vill visa den översatta NoSQL-frågan från LINQ-koden använder du ToString() metoden för det genererade IQueryable objektet. Följande beskrivning förutsätter grundläggande kunskaper om LINQ. Förutom LINQ stöder Cosmos DB även Entity Framework Core, som fungerar med API för NoSQL.

Anmärkning

Vi rekommenderar att du använder den senaste .NET SDK-versionen (Microsoft.Azure.Cosmos)

Frågeproviderns typsystem stöder endast de primitiva JSON-typerna: numeric, Boolean, stringoch null.

Frågeprovidern stöder följande skaläruttryck:

  • Konstanta värden, inklusive konstanta värden för de primitiva datatyperna vid frågeutvärderingen.

  • Egenskaps-/matrisindexuttryck som refererar till egenskapen för ett objekt eller ett matriselement. Till exempel:

    family.Id;
    family.children[0].familyName;
    family.children[0].grade;
    
    int n = 1;
    
    family.children[n].grade;
    
  • Aritmetiska uttryck, inklusive vanliga aritmetiska uttryck för numeriska och booleska värden.

    2 * family.children[0].grade;
    x + y;
    
  • Strängjämförelseuttryck, som inkluderar att jämföra ett strängvärde med ett konstant strängvärde.

    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);
    
  • Uttryck för skapande av objekt/matris, som returnerar ett objekt av sammansatt värdetyp eller anonym typ, eller en matris med sådana objekt. Du kan kapsla dessa värden.

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

Använda LINQ

Du kan skapa en LINQ-fråga med GetItemLinqQueryable. Det här exemplet visar LINQ-frågegenerering och asynkron körning med en 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-operatorer som stöds

LINQ-providern som ingår i NoSQL .NET SDK stöder följande operatorer:

  • Välj: Projektioner översätts till SELECT, inklusive objektkonstruktion.
  • Var: Filter översätts till WHEREoch stöder översättning mellan &&, ||och ! till NoSQL-operatorerna
  • SelectMany: Tillåter nedrullning av matriser till JOIN -satsen. Använd för att kedja eller kapsla uttryck för att filtrera på matriselement.
  • OrderBy och OrderByDescending: Översätt till ORDER BY med ASC eller DESC.
  • Operatorerna Count, Sum, Min, Max och Average för aggregering och deras asynkrona motsvarigheter CountAsync, SumAsync, MinAsync, MaxAsync och AverageAsync.
  • CompareTo: Översätts till intervalljämförelser. Den här operatorn används ofta för strängar eftersom strängar inte stöder < och > jämför operatorer direkt i .NET.
  • Hoppa över och ta: Översätts till OFFSET och LIMIT för att begränsa resultat från en fråga och göra sidnumrering.
  • Matematiska funktioner: Stöder översättning från .NET Abs, Acos, Asin, Atan, Ceiling, Cos, , ExpFloor, Log, Log10, PowRoundSign, Sin, Sqrt, Tanoch Truncate till motsvarande inbyggda matematiska funktioner.
  • Strängfunktioner: Stöder översättning från .NET Concat, Contains, Count, EndsWith,IndexOf , Replace, Reverse, StartsWith, Substring, ToLower, , ToUpper, TrimEndoch TrimStart till motsvarande inbyggda strängfunktioner.
  • Matrisfunktioner: Stöder översättning från .NET Concat, Containsoch Count till motsvarande inbyggda matrisfunktioner.
  • Geospatiala tilläggsfunktioner: Stöder översättning från stub-metoder Distance, IsValid, IsValidDetailedoch Within till motsvarande inbyggda geospatiala funktioner.
  • User-Defined Funktionstilläggsfunktion: Stöder översättning från stub-metoden CosmosLinq.InvokeUserDefinedFunction till motsvarande användardefinierade funktion.
  • Övrigt: Stöder översättning av Coalesce och villkorsstyrda operatorer. Kan översättas Contains till Sträng CONTAINS, ARRAY_CONTAINS, eller IN, beroende på kontext.

Examples

Följande exempel illustrerar hur några av linq-standardfrågeoperatorerna översätts till frågor i Cosmos DB.

Välj operator

Syntaxen är input.Select(x => f(x)), där f är ett skalärt uttryck. , inputi det här fallet, skulle vara ett IQueryable objekt.

Välj operator, exempel 1:

  • LINQ lambda-uttryck

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

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

Välj operator, exempel 2:

  • LINQ lambda-uttryck

    input.Select(family => family.children[0].grade + c); // c is an int variable
    
  • NoSQL

    SELECT VALUE f.children[0].grade + c
    FROM Families f
    

Välj operator, exempel 3:

  • LINQ lambda-uttryck

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

Syntaxen är input.SelectMany(x => f(x)), där f är ett skalärt uttryck som returnerar en containertyp.

  • LINQ lambda-uttryck

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

    SELECT VALUE child
    FROM Families f
    JOIN child IN f.children
    

Där operatorn

Syntaxen är input.Where(x => f(x)), där f är ett skalärt uttryck som returnerar ett booleskt värde.

Där operator, exempel 1:

  • LINQ lambda-uttryck

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

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

Där operator, exempel 2:

  • LINQ lambda-uttryck

    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
    

Sammansatta NoSQL-frågor

Du kan skapa de föregående operatorerna för att skapa mer kraftfulla frågor. Eftersom Cosmos DB stöder kapslade containrar kan du sammanfoga eller kapsla kompositionen.

Sammanlänkning

Syntaxen är input(.|.SelectMany())(.Select()|.Where())*. En sammanlänkad fråga kan börja med en valfri SelectMany fråga följt av flera Select eller Where operatorer.

Sammanfogning, exempel 1:

  • LINQ lambda-uttryck

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

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

Sammanfogning, exempel 2:

  • LINQ lambda-uttryck

    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
    

Sammanfogning, exempel 3:

  • LINQ lambda-uttryck

    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)
    

Sammanfogning, exempel 4:

  • LINQ lambda-uttryck

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

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

Häckande

Syntaxen är input.SelectMany(x=>x.Q()) där Q är en Selectoperator , SelectManyeller Where .

En kapslad fråga tillämpar den inre frågan på varje element i den yttre containern. En viktig funktion är att den inre frågan kan referera till fälten för elementen i den yttre containern, till exempel en självkoppling.

Kapsling, exempel 1:

  • LINQ lambda-uttryck

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

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

Kapsling, exempel 2:

  • LINQ lambda-uttryck

    input.SelectMany(family =>
        family.children.Where(child => child.familyName == "Jeff"));
    
  • NoSQL

    SELECT *
    FROM Families f
    JOIN c IN f.children
    WHERE c.familyName = "Jeff"
    

Kapsling, exempel 3:

  • LINQ lambda-uttryck

    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