How to model many to many connection?

Hello!
Currently i have link connection between domains. Basically a domain graph.
In sql database i have a table with many to many relation and one more field what represents how many target links was found on source domain.
SQL domain_links table:

source_domain (uint) | target_domain (uint) | links (int)
hash(domain_a.com) | hash(domain_b.com) | 3
hash(domain_a.com) | hash(domain_c.com) | 10
hash(domain_b.com) | hash(domain_c.com) | 123
...

Currently i have this schema:

name: string @index(hash) .
refdomain: [uid] @reverse .

type Domain {
    name
}

rdf example:

<0x1> <dgraph.type> "Domain" .
<0x1> <name> "domain_a.com" .

<0x2> <dgraph.type> "Domain"
<0x2> <name> "domain_b.com"

<0x3> <dgraph.type> "Domain"
<0x3> <name> "domain_c.com"

<0x2> <refdomain> <0x1>
<0x3> <refdomain> <0x1>
<0x3> <refdomain> <0x2>

My query example:

query {
  q(func: eq(name, "domain_c.com")) { 
    name
    refdomain (first: 10) {
	expand(_all_)
    }
  }
}

I want to add links field in schema and use it to sort domain by this field. But i don’t know how to correctly create many-to-many connection for graph.

Hi @hawok

I’m using GraphQL schema but you can map this to a dql schema as well:

type Domain {
  DomainID: ID!
  name: String!
}

type Connections {
  ConnectionID: ID!
  source_domain: Domain!
  target_domain: Domain!
  links: Int!
}
1 Like

Thanks for you reply! Can you show query example for this schema?

Sure. If you use the exact schema:
GraphQL Query for sorting domains based on links:

query getSortedDomains {
  queryConnections(order: {
     links: desc
  }) {
    ConnectionID
    source_domain {
     DomainID
    }
    target_domain {
     DomainID
    }
    links
  }
}

DQL equivalent:

query getSortedDomains {
  queryConnections(func: type(Connections), orderasc: Connections.links) {
    uid
    Connections.source_domain {
      uid
    }
    Connections.target_domain {
      uid
    }
    Connections.links
  }
}

Let me know if this structure solves your problem or not.

If you want to use GraphQL Layer in your app we can easily use hasInverse directive to connect domains and their connections and then query differently.

Your schema will look like this:

type Domain {
  DomainID: ID!
  name: String!
  sourceConections: [Connections]
  targetConnections: [Connections]
}

type Connections {
  ConnectionID: ID!
  source_domain: Domain! @hasInverse(field: "sourceConections")
  target_domain: Domain! @hasInverse(field: "targetConnections")
  links: Int!
}

Currently DQL is more understandable for me :slight_smile:
This schema and query works, but in other way.

Screenshot 2022-03-16 at 12.12.39

I tried this query and seems what it adds extra nodes (Connections) on graph (blue points). I need a seamless join of two domains and to see only domains nodes without “Connections” (should be 3 nodes on graph). I want to pass “links” value from Connections to “source” Domain. Is what possible? Thanks!

Yes I think that is possible. We can have a schema like this:

type Domain {
  DomainID: ID!
  source: [Domain]
  target: [Domain]
}

With a schema like this you can connect domains without Connections type. In order to handle links you can use facet and also it is feasible to sort by facets.
https://dgraph.io/docs/v21.03/query-language/facets/

Thanks, i will dig in it.