Eseguire una query su elementi in Azure Cosmos DB for NoSQL con .NET

SI APPLICA A: NoSQL

Gli elementi in Azure Cosmos DB rappresentano le entità archiviate all'interno di un contenitore. Nell'API per NoSQL, un elemento è costituito da dati formattati per JSON con un identificatore univoco. Quando si eseguono query usando l'API per NoSQL, i risultati vengono restituiti come matrice JSON di documenti JSON.

Eseguire query usando SQL

Azure Cosmos DB per NoSQL supporta l'uso di Structured Query Language (SQL) per eseguire query su elementi presenti all'interno di contenitori. Una query SQL semplice come SELECT * FROM products restituisce tutti gli elementi e tutte le proprietà da un contenitore. Le query possono essere ancora più complesse e includere proiezioni di campi, filtri e altre clausole SQL comuni:

SELECT 
    p.name, 
    p.description AS copy
FROM 
    products p 
WHERE 
    p.price > 500

Per ottenere maggiori informazioni sulla sintassi SQL per Azure Cosmos DB per NoSQL, consultare Query in Azure Cosmos DB per NoSQL.

Eseguire una query su un elemento

Nota

Gli esempi forniti in questo articolo presuppongono che sia già stato definito un tipo C# per rappresentare i dati denominati Product:

// C# record type for items in the container
public record Product(
    string id,
    string category,
    string name,
    int quantity,
    bool sale
);

Per eseguire query in un contenitore, usare uno dei metodi seguenti:

Eseguire query sugli elementi usando una query SQL in modo asincrono

Questo esempio compila una query SQL usando una stringa semplice, recupera un iteratore di feed e quindi usa cicli annidati per eseguire l'iterazione dei risultati. Il ciclowhile esterno eseguirà l'iterazione delle pagine dei risultati, mentre il ciclo foreach interno esegue l'iterazione dei risultati all'interno di una pagina.

// Query multiple items from container
using FeedIterator<Product> feed = container.GetItemQueryIterator<Product>(
    queryText: "SELECT * FROM products p WHERE p.quantity > 10"
);

// Iterate query result pages
while (feed.HasMoreResults)
{
    FeedResponse<Product> response = await feed.ReadNextAsync();

    // Iterate query results
    foreach (Product item in response)
    {
        Console.WriteLine($"Found item:\t{item.name}");
    }
}

Il metodo Container.GetItemQueryIterator<> restituisce un oggetto FeedIterator<> utilizzato per eseguire l'iterazione dei risultati a più pagine. La proprietà HasMoreResults indica se sono rimaste più pagine di risultati. Il metodo ReadNextAsync mostra la pagina successiva dei risultati come enumerabile che viene quindi utilizzata in un ciclo per eseguire l'iterazione dei risultati.

In alternativa, usare QueryDefinition per compilare una query SQL con input con parametri:

// Build query definition
var parameterizedQuery = new QueryDefinition(
    query: "SELECT * FROM products p WHERE p.quantity > @quantity"
)
    .WithParameter("@quantity", 10);

// Query multiple items from container
using FeedIterator<Product> filteredFeed = container.GetItemQueryIterator<Product>(
    queryDefinition: parameterizedQuery
);

// Iterate query result pages
while (filteredFeed.HasMoreResults)
{
    FeedResponse<Product> response = await filteredFeed.ReadNextAsync();

    // Iterate query results
    foreach (Product item in response)
    {
        Console.WriteLine($"Found item:\t{item.name}");
    }
}

Suggerimento

I valori di input con parametri consentono di prevenire molti attacchi comuni di inserimento di query SQL.

Eseguire query usando LINQ in modo asincrono

Nell'esempio riportato di seguito, viene usato un oggetto IQueryable<> per costruire un LINQ (Language Integrated Query). I risultati vengono quindi iterati usando un iteratore di feed.

// Get LINQ IQueryable object
IOrderedQueryable<Product> queryable = container.GetItemLinqQueryable<Product>();

// Construct LINQ query
var matches = queryable
    .Where(p => p.quantity > 10);

// Convert to feed iterator
using FeedIterator<Product> linqFeed = matches.ToFeedIterator();

// Iterate query result pages
while (linqFeed.HasMoreResults)
{
    FeedResponse<Product> response = await linqFeed.ReadNextAsync();

    // Iterate query results
    foreach (Product item in response)
    {
        Console.WriteLine($"Matched item:\t{item.name}");
    }
}

Il metodo Container.GetItemLinqQueryable<> costruisce un oggetto IQueryable per compilare la query LINQ. Viene quindi usato il metodo ToFeedIterator<> per convertire l'espressione di query LINQ in un oggettoFeedIterator<>.

Suggerimento

Sebbene sia possibile eseguire l'iterazione su IQueryable<>, questa operazione è sincrona. Usare il metodo ToFeedIterator<> per raccogliere i risultati in modo asincrono.

Passaggi successivi

Dopo aver eseguito query su più elementi, provare una delle esercitazioni end-to-end con l'API per NoSQL.