Lavorando semrpe alla POC per l’applicazione del Digital Decoupling su CRM sto sviluppando un servizio di raccomandazione prodotti che usa l’algoritmo K-NN e la Cosine similiarity per consigliare dato un prodotto, un acquisto “collegato”. Parte di questo lavoro richeideva di caricare all’interno di CosmosDB una serie di dati sotto forma di Graph - dopo qualche ricerca i sono imbattuto nella libreria Gremlin.NET per CosmosDB GitHub qui. DOpo qualche riga di codice, sono riuscito a creare un grafo bello connesso in questo modo:

using (var graphClient = new GraphClient("azure.gremlin.cosmos.azure.com", "dbname", "graphname","secret"))
{
    var g = graphClient.CreateTraversalSource();

    foreach (var gremlinItem in gremlinItems)
    {
        var item = g.AddV(gremlinItem.Master).As("person")
                    .AddV(gremlinItem.Slave).As("part")
                    .AddE(gremlinItem.Edge).From("person").To("part");

        await graphClient.QueryAsync(item.ToGremlinQuery());
    }
}

Costruttore a parte, dopo aver creato un IGraphTraversalSource cicliamo su quella che è una lista (di oggetto GremlinItem) (calcolata da me leggendo da un CSV) di item che vogliamo relazionare tra loro. L’SDK di Gramlin per Cosmos offre un meccanismo tipizzato per permetterci di creare dei model che permettano di definire le relazioni tramite oggetti POCO.

using Gremlin.Net.CosmosDb.Structure;

namespace Blog.DD.Graph.Loader.Models
{
    public class GremlinItem
    {
        public PersonVertex Master { get; set; }
        public PartVertex Slave { get; set; }
        public PersonPurchasedPartEdge Edge { get; set; }
    }

    [Label("person")]
    public class PersonVertex : IVertex
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public PersonPurchasedPartEdge Purchases { get; }
    }

    [Label("part")]
    public sealed class PartVertex : IVertex
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public PersonPurchasedPartEdge People { get; }
    }

    [Label("purchased")]
    public sealed class PersonPurchasedPartEdge : ManyToManyEdge<PersonVertex, PartVertex>
    {
        public int Rating { get; set; }
    }
}

Una volta terminato il submite delle query per tutti gli elementi della vista, il risultato su CosmosDB è il seguente (il visualizer è una estensione di VSCode):