Azure Cosmos DB: Sviluppare con l'API Graph in .NET

Azure Cosmos DB è il servizio di database di Microsoft multimodello distribuito a livello globale. È possibile creare ed eseguire rapidamente query su database di documenti, coppie chiave-valore e grafi, sfruttando in ognuno dei casi i vantaggi offerti dalle funzionalità di scalabilità orizzontale e distribuzione globale alla base di Azure Cosmos DB.

Questa esercitazione illustra come creare un account Azure Cosmos DB usando il portale di Azure e come creare un contenitore e un database di grafi. L'applicazione crea quindi una social network semplice con quattro utenti usando l'API Graph (anteprima), quindi attraversa ed esegue query sul grafo usando Gremlin.

Questa esercitazione illustra le attività seguenti:

  • Creare un account Azure Cosmos DB
  • Creare un contenitore e un database di grafi
  • Serializzare vertici e archi negli oggetti .NET
  • Aggiungere vertici e archi
  • Eseguire query sul grafo usando Gremlin

Grafi in Azure Cosmos DB

È possibile usare Azure Cosmos DB per creare, aggiornare ed eseguire query di grafi usando la libreria Microsoft.Azure.Graphs. La libreria Microsoft.Azure.Graph offre un metodo di estensione singolo CreateGremlinQuery<T> oltre alla classe DocumentClient per eseguire query Gremlin.

Il linguaggio di programmazione funzionale Gremlin supporta operazioni di scrittura (DML) e le operazioni di query e attraversamento. Questo articolo descrive alcuni esempi per iniziare a usare Gremlin. Vedere Query di Gremlin per una procedura dettagliata delle funzionalità Gremlin disponibili in Azure Cosmos DB.

Prerequisiti

Assicurarsi di disporre di quanto segue:

Creare un account di database

Si inizia creando un account Azure Cosmos DB nel portale di Azure.

Suggerimento
  1. In una nuova finestra accedere al portale di Azure.
  2. Nel riquadro a sinistra fare clic su Nuovo, quindi su Database e infine su Azure Cosmos DB.

    Riquadro Database nel portale di Azure

  3. Nel pannello Nuovo account specificare la configurazione desiderata per l'account Azure Cosmos DB.

    Con Azure Cosmos DB è possibile scegliere uno dei quattro modelli di programmazione: Gremlin (grafo), MongoDB, SQL (DocumentDB) e Tabella (chiave/valore), ognuno dei quali attualmente richiede un account separato.

    In questa guida introduttiva viene eseguita la programmazione in base all'API Graph, quindi scegliere Gremlin (grafo) quando si compila il modulo. Se si hanno tuttavia dati di documenti di un'app di catalogo, dati chiave/valore (tabella) o dati di cui è stata eseguita la migrazione da un'app MongoDB, tenere presente che Azure Cosmos DB può fornire una piattaforma di servizi di database con distribuzione a livello globale e a disponibilità elevata per tutte le applicazioni cruciali.

    Completare i campi nel pannello Nuovo account usando le informazioni riportate nello screenshot seguente come guida. I valori effettivi potrebbero essere diversi.

    Pannello Nuovo account per Azure Cosmos DB

    Impostazione Valore consigliato Descrizione
    ID Valore univoco Nome univoco che identifica l'account Azure Cosmos DB. Poiché alI'ID fornito viene aggiunto documents.azure.com per creare l'URI, usare un ID univoco ma facilmente identificabile. L'ID deve contenere solo lettere minuscole, numeri e il segno meno (-) e deve avere una lunghezza compresa tra 3 e 50 caratteri.
    API Gremlin (graph) La programmazione in base all'API Graph verrà eseguita più avanti in questo articolo.
    Sottoscrizione Sottoscrizione in uso Sottoscrizione di Azure da usare per l'account Azure Cosmos DB.
    Gruppo di risorse Stesso valore di ID Nome del nuovo gruppo di risorse per l'account. Per semplicità si può usare lo stesso nome usato come ID.
    Località Area più vicina ai propri utenti Posizione geografica in cui ospitare l'account Azure Cosmos DB. Scegliere la posizione più vicina ai propri utenti per fornire loro l'accesso più rapido possibile ai dati.
  4. Fare clic su Crea per creare l'account.

  5. Nella barra degli strumenti superiore fare clic sull'icona delle notifiche icona delle notifiche per monitorare il processo di distribuzione.

    Riquadro Notifiche del portale di Azure

  6. Quando la finestra Notifiche indica che la distribuzione è stata completata, chiudere la finestra di notifica e aprire il nuovo account dal riquadro Tutte le risorse nel Dashboard.

    Account DocumentDB nel riquadro Tutte le risorse

Configurare la soluzione di Visual Studio

  1. Aprire Visual Studio nel computer.
  2. Scegliere Nuovo dal menu File e quindi selezionare Progetto.
  3. Nella finestra di dialogo Nuovo progetto selezionare Modelli / Visual C# / App console (.NET Framework), assegnare un nome al progetto e quindi fare clic su OK.
  4. In Esplora soluzioni fare clic con il pulsante destro del mouse sulla nuova applicazione console, disponibile nella soluzione di Visual Studio, quindi scegliere Gestisci pacchetti NuGet.
  5. Nella scheda NuGet fare clic su Sfogliae digitare Microsoft.Azure.Graphs nella casella di ricerca e selezionare Includi versione preliminare.
  6. Nei risultati trovare Microsoft.Azure.Graphs e fare clic su Installa.

    Se viene visualizzato un messaggio sulla verifica delle modifiche alla soluzione, fare clic su OK. Se viene visualizzato un messaggio sull'accettazione della licenza, fare clic su Accetto.

    La libreriaMicrosoft.Azure.Graphs fornisce un metodo di estensione singolo CreateGremlinQuery<T> per l'esecuzione di operazioni Gremlin. Il linguaggio di programmazione funzionale Gremlin supporta operazioni di scrittura (DML) e le operazioni di query e attraversamento. Questo articolo descrive alcuni esempi per iniziare a usare Gremlin. Query Gremlin include una procedura dettagliata delle funzionalità di Gremlin in Azure Cosmos DB.

Connessione dell'app

Aggiungere queste due costanti e la variabile client nell'applicazione.

string endpoint = ConfigurationManager.AppSettings["Endpoint"]; 
string authKey = ConfigurationManager.AppSettings["AuthKey"]; 

Tornare al portale di Azure per recuperare la chiave primaria e l'URL dell'endpoint. L'URL e la chiave primaria dell'endpoint sono necessari all'applicazione per conoscere la destinazione della connessione e ad Azure Cosmos DB per considerare attendibile la connessione dell'applicazione.

Nel portale di Azure passare all'account Azure Cosmos DB, fare clic su Chiavi, quindi su Chiavi di lettura/scrittura.

Copiare l'URI dal portale e incollarlo su Endpoint nella proprietà dell'endpoint. Copiare quindi la CHIAVE PRIMARIA dal portale e incollarla nella proprietà AuthKey precedente.

![Screenshot del portale di Azure usato nell'esercitazione per creare un'applicazione C#. Mostra un account Azure Cosmos DB, il pulsante CHIAVI evidenziato nel Pannello di navigazione Azure Cosmos DB e i valori URI e CHIAVE PRIMARIA evidenziati nel pannello chiavi] [keys]

Creare un'istanza di DocumentClient

Creare quindi una nuova istanza di DocumentClient.

DocumentClient client = new DocumentClient(new Uri(endpoint), authKey); 

Creare un database

A questo punto creare un database di Azure Cosmos DB usando il metodo CreateDatabaseAsync o CreateDatabaseIfNotExistsAsync della classe DocumentClient da DocumentDB .NET SDK.

Database database = await client.CreateDatabaseIfNotExistsAsync(new Database { Id = "graphdb" }); 

Creare un grafo

Creare quindi un contenitore di grafi usando il metodo CreateDocumentCollectionAsync o CreateDocumentCollectionIfNotExistsAsync della classe DocumentClient. Una raccolta è un contenitore di entità di grafi.

DocumentCollection graph = await client.CreateDocumentCollectionIfNotExistsAsync( 
    UriFactory.CreateDatabaseUri("graphdb"), 
    new DocumentCollection { Id = "graphcollz" }, 
    new RequestOptions { OfferThroughput = 1000 }); 

Serializzare vertici e archi negli oggetti .NET

Azure Cosmos DB usa il formato wire GraphSON, che definisce uno schema JSON per vertici, archi e proprietà. Azure Cosmos DB .NET SDK include JSON.NET come dipendenza e ciò consente di serializzare o deserializzare GraphSON negli oggetti .NET che è possibile usare nel codice.

Ad esempio, è possibile usare una social network semplice con quattro utenti. Verrà illustrato come creare vertici Person, aggiungere relazioni Knows tra i vertici, quindi eseguire query e attraversare il grafo per individuare le relazioni "amico di amico".

Lo spazio dei nomi Microsoft.Azure.Graphs.Elements fornisce le classi Vertex, Edge, Property e VertexProperty per la deserializzazione delle risposte GraphSON a oggetti .NET ben definiti.

Eseguire Gremlin usando CreateGremlinQuery

Gremlin, come SQL, supporta le operazioni di lettura, scrittura e le query. Ad esempio, il frammento seguente illustra come creare vertici e archi, eseguire alcune query di esempio usando CreateGremlinQuery<T> e iterare in modo asincrono questi risultati usando ExecuteNextAsync e 'HasMoreResults.

Dictionary<string, string> gremlinQueries = new Dictionary<string, string>
{
    { "Cleanup",        "g.V().drop()" },
    { "AddVertex 1",    "g.addV('person').property('id', 'thomas').property('firstName', 'Thomas').property('age', 44)" },
    { "AddVertex 2",    "g.addV('person').property('id', 'mary').property('firstName', 'Mary').property('lastName', 'Andersen').property('age', 39)" },
    { "AddVertex 3",    "g.addV('person').property('id', 'ben').property('firstName', 'Ben').property('lastName', 'Miller')" },
    { "AddVertex 4",    "g.addV('person').property('id', 'robin').property('firstName', 'Robin').property('lastName', 'Wakefield')" },
    { "AddEdge 1",      "g.V('thomas').addE('knows').to(g.V('mary'))" },
    { "AddEdge 2",      "g.V('thomas').addE('knows').to(g.V('ben'))" },
    { "AddEdge 3",      "g.V('ben').addE('knows').to(g.V('robin'))" },
    { "UpdateVertex",   "g.V('thomas').property('age', 44)" },
    { "CountVertices",  "g.V().count()" },
    { "Filter Range",   "g.V().hasLabel('person').has('age', gt(40))" },
    { "Project",        "g.V().hasLabel('person').values('firstName')" },
    { "Sort",           "g.V().hasLabel('person').order().by('firstName', decr)" },
    { "Traverse",       "g.V('thomas').outE('knows').inV().hasLabel('person')" },
    { "Traverse 2x",    "g.V('thomas').outE('knows').inV().hasLabel('person').outE('knows').inV().hasLabel('person')" },
    { "Loop",           "g.V('thomas').repeat(out()).until(has('id', 'robin')).path()" },
    { "DropEdge",       "g.V('thomas').outE('knows').where(inV().has('id', 'mary')).drop()" },
    { "CountEdges",     "g.E().count()" },
    { "DropVertex",     "g.V('thomas').drop()" },
};

foreach (KeyValuePair<string, string> gremlinQuery in gremlinQueries)
{
    Console.WriteLine($"Running {gremlinQuery.Key}: {gremlinQuery.Value}");

    // The CreateGremlinQuery method extensions allow you to execute Gremlin queries and iterate
    // results asychronously
    IDocumentQuery<dynamic> query = client.CreateGremlinQuery<dynamic>(graph, gremlinQuery.Value);
    while (query.HasMoreResults)
    {
        foreach (dynamic result in await query.ExecuteNextAsync())
        {
            Console.WriteLine($"\t {JsonConvert.SerializeObject(result)}");
        }
    }

    Console.WriteLine();
}

Aggiungere vertici e archi

Verranno esaminati in maggiore dettaglio i comandi Gremlin illustrati nella sezione precedente. Prima si aggiungono vertici usando il metodo addV Gremlin. Ad esempio, il frammento seguente crea un vertice "Thomas Andersen" di tipo "Person", con proprietà per il nome, il cognome e l'età.

// Create a vertex
IDocumentQuery<Vertex> createVertexQuery = client.CreateGremlinQuery<Vertex>(
    graphCollection, 
    "g.addV('person').property('firstName', 'Thomas')");

while (createVertexQuery.HasMoreResults)
{
    Vertex thomas = (await create.ExecuteNextAsync<Vertex>()).First();
}

Creare quindi alcuni archi tra i vertici usando il metodo addE Gremlin.

// Add a "knows" edge
IDocumentQuery<Edge> createEdgeQuery = client.CreateGremlinQuery<Edge>(
    graphCollection, 
    "g.V('thomas').addE('knows').to(g.V('mary'))");

while (create.HasMoreResults)
{
    Edge thomasKnowsMaryEdge = (await create.ExecuteNextAsync<Edge>()).First();
}

È possibile aggiornare un vertice esistente usando il comando properties Gremlin. Non verrà esaminata la chiamata per eseguire la query tramite HasMoreResults e ExecuteNextAsync negli altri esempi.

// Update a vertex
client.CreateGremlinQuery<Vertex>(
    graphCollection, 
    "g.V('thomas').property('age', 45)");

È possibile trascinare gli archi e i vertici usando il comando drop Gremlin. Ecco un frammento di codice che illustra come eliminare un vertice e un arco. Si noti che l'eliminazione di un vertice implica l'eliminazione a catena degli archi associati.

// Drop an edge
client.CreateGremlinQuery(graphCollection, "g.E('thomasKnowsRobin').drop()");

// Drop a vertex
client.CreateGremlinQuery(graphCollection, "g.V('robin').drop()");

Eseguire una query sul grafo

È possibile anche eseguire operazioni di query e attraversamento usando Gremlin. Ad esempio, il frammento seguente illustra come contare il numero di vertici nel grafo:

// Run a query to count vertices
IDocumentQuery<int> countQuery = client.CreateGremlinQuery<int>(graphCollection, "g.V().count()");

È possibile eseguire filtri usando i comandi has e hasLabel Gremlin e combinarli usando and, or e not per creare filtri più complessi:

// Run a query with filter
IDocumentQuery<Vertex> personsByAge = client.CreateGremlinQuery<Vertex>(
  graphCollection, 
  "g.V().hasLabel('person').has('age', gt(40))");

È possibile proiettare determinate proprietà nei risultati della query usando il comando values:

// Run a query with projection
IDocumentQuery<string> firstNames = client.CreateGremlinQuery<string>(
  graphCollection, 
  $"g.V().hasLabel('person').values('firstName')");

Finora sono stati esaminati solo gli operatori di query che è possibile usare in qualsiasi database. I grafi sono veloci ed efficienti per le operazioni di attraversamento quando è necessario passare agli archi e ai vertici correlati. Verranno ora individuati tutti gli amici di Thomas. Questa operazione viene eseguita usando il comando outE di Gremlin per individuare tutti gli archi in uscita da Thomas, quindi attraversando i vertici in ingresso da tali archi usando il comando inV di Gremlin:

// Run a traversal (find friends of Thomas)
IDocumentQuery<Vertex> friendsOfThomas = client.CreateGremlinQuery<Vertex>(
  graphCollection,
  "g.V('thomas').outE('knows').inV().hasLabel('person')");

La query successiva esegue due passaggi per trovare tutti "gli amici di amici" di Thomas chiamando outE e inV due volte.

// Run a traversal (find friends of friends of Thomas)
IDocumentQuery<Vertex> friendsOfFriendsOfThomas = client.CreateGremlinQuery<Vertex>(
  graphCollection,
  "g.V('thomas').outE('knows').inV().hasLabel('person').outE('knows').inV().hasLabel('person')");

È possibile creare query più complesse e implementare la potente logica di attraversamento di grafi usando Gremlin, incluse la combinazione di espressioni di filtro, l'esecuzione di cicli con il comando loop e l'implementazione dello spostamento condizionale usando il comando choose. Altre informazioni sulle operazioni che è possibile eseguire con il supporto per Gremlin.

L'esercitazione di Azure Cosmos DB è stata completata.

Pulire le risorse

Se non si prevede di continuare a usare questa app, seguire questa procedura per eliminare tutte le risorse create da questa esercitazione nel portale di Azure.

  1. Scegliere Gruppi di risorse dal menu a sinistra del portale di Azure e quindi fare clic sul nome della risorsa creata.
  2. Nella pagina del gruppo di risorse fare clic su Elimina, digitare il nome della risorsa da eliminare nella casella di testo e quindi fare clic su Elimina.

Passaggi successivi

In questa esercitazione sono state eseguite le operazioni seguenti:

  • Creazione di un account Azure Cosmos DB
  • Creazione di un contenitore e un database di grafi
  • Serializzazione di vertici e archi negli oggetti .NET
  • Aggiunta di vertici e archi
  • Esecuzione di query sul grafo usando Gremlin

È ora possibile creare query più complesse e implementare la potente logica di attraversamento di grafi usando Gremlin.