question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

How to query a Graph and instantiate C# Classes with the data?

See original GitHub issue

Suppose I have C# classes like Customer, Invoice, Invoice Items, and these have the corresponding Nodes on Neo4j Graph. How can I query the graph and instantiate these objects and the relations?

Now I do the Cypher Query to read this Graph and follow it the way I need, by grouping the main nodes, a foreach iterating the sub nodes grouping them, and instantiating the C# classes and putting the data on the classes using the Customer = client.Return<Customer>…

I am using this wonderful neo4j Driver, and need a better, cleaner, way to “transfer” my graph that I just queried into my C# classes and related classes. Please give me some light on this 😃 Is there some example online you can point to me?

This is the graph: (Pessoa:Pessoa)-[:Possui]->(PeriodoAtividade:PeriodoAtividade)-[:Possui]->(Turno:Turno)

image

Suppose I query it using:

MATCH (Pessoa:Pessoa { id: "aac9f060-e838-48e9-8a42-0f1c22040abc" })-[:Possui]->(CoordenacaoPedagogica:CoordenacaoPedagogica)-[:Possui]->(PeriodoAtividade:PeriodoAtividade)
OPTIONAL MATCH (PeriodoAtividade)-[:Possui]->(Turno:Turno)
OPTIONAL MATCH (PeriodoAtividade)-[:Possui]->(UnidadeLetiva:UnidadeLetiva)
RETURN CoordenacaoPedagogica AS CoordenacaoPedagogica, PeriodoAtividade AS PeriodoAtividade, UnidadeLetiva AS UnidadeLetiva, Turno AS Turno
ORDER BY Turno.Titulo, UnidadeLetiva.Titulo

The classes look like this:

[AddINotifyPropertyChangedInterface]
public class CoordenacaoPedagogica
{
    public class Dados : IDados
    {
        public Guid id { get; set; } = Guid.NewGuid();
        public Guid TenantID { get; set; }
    }
    public Dados Propriedades { get; set; } = new Dados();

    [Relacao("Possui", DirecaoRelacao.In)]
    public Pessoa.Pessoa Empresa { get; set; }

    [Relacao("Possui", DirecaoRelacao.Out)]
    public ObservableCollection<PeriodoAtividade> PeriodoAtividade { get; set; } = new ObservableCollection<PeriodoAtividade>();
}

[AddINotifyPropertyChangedInterface]
public class PeriodoAtividade
{
    public class Dados : IDados
    {
        public Guid id { get; set; } = Guid.NewGuid();
        public Guid TenantID { get; set; }

        public DateTime DataHoraInicial { get; set; }
        public DateTime DataHoraFinal { get; set; }

        public string Titulo { get; set; }  // 2020   ou I Semestre 2020    ou Semi-Extensivo 2020
    }
    public Dados Propriedades { get; set; } = new Dados();

    [Relacao("Possui", DirecaoRelacao.In)]
    public CoordenacaoPedagogica CoordenacaoPedagogica { get; set; }

    [Relacao("Possui", DirecaoRelacao.Out)]
    public ObservableCollection<UnidadeLetiva> UnidadesLetivas { get; set; } = new ObservableCollection<UnidadeLetiva>();

    [Relacao("Possui", DirecaoRelacao.Out)]
    public ObservableCollection<Turno> Turnos { get; set; } = new ObservableCollection<Turno>();
}

public class UnidadeLetiva
{
    public class Dados : IDados
    {
        public Guid id { get; set; }//= Guid.NewGuid();
        public Guid TenantID { get; set; }

        public DateTime DataHoraInicial { get; set; }
        public DateTime DataHoraFinal { get; set; }

        public string Titulo { get; set; }  // 2020   ou I Semestre 2020    ou Semi-Extensivo 2020
    }
    public Dados Propriedades { get; set; } = new Dados();

    [Relacao("Possui", DirecaoRelacao.In)]
    public PeriodoAtividade PeriodoAtividade { get; set; }

    [Relacao("Possui", DirecaoRelacao.Out)]
    public ObservableCollection<Avaliacao> Avaliacoes { get; set; } = new ObservableCollection<Avaliacao>();
}

[AddINotifyPropertyChangedInterface]
public class Turno
{
    public class Dados : IDados
    {
        public Guid id { get; set; } = Guid.NewGuid();
        public Guid TenantID { get; set; }

        public string Titulo { get; set; }  // exemplo Matutino, Vespertino, Noturno

        public DateTime DataHoraInicial { get; set; }
        public DateTime DataHoraFinal { get; set; }
    }
    public Dados Propriedades { get; set; } = new Dados();

    [Relacao("PeriodoAtividade", DirecaoRelacao.In)]
    public PeriodoAtividade PeriodoAtividade { get; set; }

    [Relacao("Possui", DirecaoRelacao.Out)]
    public ObservableCollection<Turma> Turmas { get; set; } = new ObservableCollection<Turma>();
}

Now my code to instantiate the classes looks like this:

public static async Task<CoordenacaoPedagogica> PegaCoordenacaoPedagogica(Guid PessoaID)
{
    using (var client = await neo4jh.TryGetClientConnectedAsync())
    {
        var q = client.Cypher
            .Match(
                "(Pessoa:Pessoa { id: {PessoaID} })-[:Possui]->(CoordenacaoPedagogica:CoordenacaoPedagogica)-[:Possui]->(PeriodoAtividade:PeriodoAtividade)"
            )
            .OptionalMatch("(PeriodoAtividade)-[:Possui]->(Turno:Turno)")
            .OptionalMatch("(PeriodoAtividade)-[:Possui]->(UnidadeLetiva:UnidadeLetiva)")
            .WithParam("PessoaID", PessoaID)
            .Return
            (
                (CoordenacaoPedagogica, PeriodoAtividade, UnidadeLetiva, Turno) => new
                {
                    CoordenacaoPedagogica = CoordenacaoPedagogica.As<CoordenacaoPedagogica.Dados>(),
                    PeriodoAtividade = PeriodoAtividade.As<PeriodoAtividade.Dados>(),
                    UnidadeLetiva = UnidadeLetiva.As<UnidadeLetiva.Dados>(),
                    Turno = Turno.As<Turno.Dados>()
                }
            )
            .OrderBy("Turno.Titulo, UnidadeLetiva.Titulo")
            ;
        var r = await q.ResultsAsync;

        var Pessoa = new Pessoa();
                
        var list_CoordenacaoPedagogica = (
                                            from result in r
                                            group result by result.CoordenacaoPedagogica.id into g
                                            select new { ItemId = g.Key, SubItems = g }
                                            ).ToList();

        foreach (var gCoordenacaoPedagogica in list_CoordenacaoPedagogica)
        {
            var CoordenacaoPedagogica_ = new CoordenacaoPedagogica()
            {
                Propriedades = list_CoordenacaoPedagogica.First().SubItems.First().CoordenacaoPedagogica
            };
            Pessoa.CoordenacoesPedagogicas.Add(CoordenacaoPedagogica_);

            var list_PeriodoAtividade = (from PeriodoAtividade in gCoordenacaoPedagogica.SubItems
                                            group PeriodoAtividade by PeriodoAtividade.PeriodoAtividade.id into g
                                            select new { ItemId = g.Key, SubItems = g }
                                            ).ToList();

            foreach (var gPeriodoAtividade in list_PeriodoAtividade)
            {
                PeriodoAtividade Periodo = new PeriodoAtividade()
                {
                    Propriedades = gPeriodoAtividade.SubItems.First().PeriodoAtividade
                };
                CoordenacaoPedagogica_.PeriodoAtividade.Add(Periodo);

                var list_Turno = (from Turno in gPeriodoAtividade.SubItems
                                    group Turno by Turno.Turno.id into g
                                    select new { ItemId = g.Key, SubItems = g }
                                    ).ToList();
                foreach (var gTurno in list_Turno)
                {
                    var Turno = new Turno()
                    {
                        Propriedades = gTurno.SubItems.First().Turno
                    };
                    Periodo.Turnos.Add(Turno);
                }

                var list_UnidadeLetiva = (from UnidadeLetiva in gPeriodoAtividade.SubItems
                                            where UnidadeLetiva.UnidadeLetiva?.id != Guid.Empty
                                            group UnidadeLetiva by UnidadeLetiva.UnidadeLetiva?.id into g
                                            select new { ItemId = g.Key, SubItems = g }
                                            ).ToList();
                foreach (var gUnidadeLetiva in list_UnidadeLetiva)
                {
                    var ul = gUnidadeLetiva.SubItems.First().UnidadeLetiva;
                    if (ul != null)
                    {
                        var UnidadeLetiva = new UnidadeLetiva()
                        {
                            Propriedades = ul
                        };
                        Periodo.UnidadesLetivas.Add(UnidadeLetiva);
                    }
                }
            }
        }

        return Pessoa.CoordenacoesPedagogicas.First();
    }
}

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:8 (5 by maintainers)

github_iconTop GitHub Comments

2reactions
cskardoncommented, Sep 22, 2020

Hey @TonyHenrique Sorry for the delay in this - I missed it 😦

I have this graph: image

These classes:

public class Item
{
	public int Id { get; set; }
	public string Name { get; set; }
}

public class Customer
{
	public int Id { get; set; }
	public string Name { get; set; }
}

public class Invoice
{
	public int InvoiceId { get; set; }
	public IEnumerable<Item> Items { get; set; }
}

public class CustomerAndInvoices
{
	public Customer Customer { get; set; }
	public IEnumerable<Invoice> Invoices { get; set; }
}

Which I fill up with this code:

var query = client.Cypher
	.Match("(c:Customer)-[:HAS_INVOICE]->(inv:Invoice)-[:CONTAINS]->(i:Item)")
	.Where((Customer c) => c.Id == 1)
	.With("c, {InvoiceId: inv.Id, Items: COLLECT(i)} AS invoiceWithItems")
	.With("{Customer: c, Invoices: COLLECT(invoiceWithItems)} AS customerWithInvoices")
	.Return(customerWithInvoices => customerWithInvoices.As<CustomerAndInvoices>());

var results = await query.ResultsAsync;

Which gives me this:

image

Is this doing what you wanted?

The Cypher query is:

MATCH (c:Customer)-[:HAS_INVOICE]->(inv:Invoice)-[:CONTAINS]->(i:Item)
WHERE (c.Id = 1)
WITH c, {InvoiceId: inv.Id, Items: COLLECT(i)} AS invoiceWithItems
WITH {Customer: c, Invoices: COLLECT(invoiceWithItems)} AS customerWithInvoices
RETURN customerWithInvoices

To instantiate a DB - you can use:

CREATE (i1:Item {Id: 1, Name: 'Kettle'})
CREATE (i2:Item {Id: 2, Name: 'Teapot'})
CREATE (i3:Item {Id: 3, Name: 'Tea'})
CREATE (i4:Item {Id: 4, Name: 'Coffee Pot'})
CREATE (i5:Item {Id: 5, Name: 'Coffee'})

CREATE (c1:Customer {Id:1, Name:'Chris'})-[:HAS_INVOICE]->(inv1:Invoice {Id: 1, Phone: '+00123456'})
CREATE (c2:Customer {Id:2, Name:'Tony'})-[:HAS_INVOICE]->(inv2:Invoice {Id: 1, Phone: '+02654987'})
CREATE (c1)-[:HAS_INVOICE]->(inv3:Invoice {Id:3, Phone:'+024455321'})

CREATE (inv1)-[:CONTAINS]->(i1)
CREATE (inv1)-[:CONTAINS]->(i2)

CREATE (inv2)-[:CONTAINS]->(i1)
CREATE (inv2)-[:CONTAINS]->(i4)
CREATE (inv2)-[:CONTAINS]->(i5)

CREATE (inv3)-[:CONTAINS]->(i3)
1reaction
cskardoncommented, Nov 2, 2020

I’m going to close this now - please reopen if you need to!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Class graph Neo4j query
I have built a a class graph of legacy code base with Neo4j. I'm trying to query for all the methods of parent...
Read more >
How to Create Conditional and Dynamic Queries in ...
The logic behind this search phrase is: 1️⃣ Create Search Phrase. Enter search phrase text with the conditional parameters $label. , $property , ......
Read more >
Data Queries | Charts
Instantiate a Query object with the URL of your Datasource. The URL should indicate what data is being requested, in a syntax understood...
Read more >
The Complete Cypher Cheat Sheet
Introduction. Cypher is the most widely adopted, fully specified, and open query language for property graph databases.
Read more >
Neo4j (Graph Database) Crash Course - YouTube
In this video, we will cover neo4j which is a graph database Second ... Nodes 48:00 - Querying for Relationships 1:00:00 - Aggregating...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found