Traverse on different types

I’ve seen that traversing recursively on nodes of the same entity is pretty straightforward but I’m having trouble writing a query that could traverse through different entities. I don’t know if I can achieve that with DQL or if it would be better to get what I want using a graph analysis after querying the database.

Here’s an example:

type City {
  Id: ID
  Name: String
  Paths: [Path]
}

type Path {
  Destination: City
  Type: String
  Cost: Int
  Minutes:Int
}

So let’s say I have a graph of cities connected by paths which can be of types [“train”, "boat, “car”], each one associated with a ticket cost.

To get from city A to city Z there are many different ways and many cities in between that we could stop to make another leg of the trip.

If I wanna display which are all the possible routes, what is the cheapest, which are all the routes that do not take a train etc, I could load all cities and paths in memory and apply recursive functions or whatever locally but I’m wondering if I can use traversals and recursions to do it while querying the db.

Is there any way to make a custom query with DQL and recursion to get, for example, the path with less stops from city A to city Z using only paths of “car” type?

Hi @brmaeji I’m speaking with the team and we’ll be sure to get your questions answered. Best,
Derek

Hi Brenno,
Please review the shortest path implementation in Dgraph here. The implementation relies on facets to provide weights.

Here is an example that might interest you. (Car and Bus movement for each relation is modeled as facets and specified in the shortest query)

{
  set {
    _:a <friend> _:b (weightCar=10, weightBus=1 ) .
    _:b <friend> _:c (weightCar=20, weightBus=1) .
    _:c <friend> _:d (weightCar=11, weightBus=1.1) .
    _:a <friend> _:d (weightCar=70, weightBus=2) .
    _:a <name> "Alice7" .
    _:a <dgraph.type> "Person" .
    _:b <name> "Bob7" .
    _:b <dgraph.type> "Person" .
    _:c <name> "Tom7" .
    _:c <dgraph.type> "Person" .
    _:d <name> "Mallory7" .
    _:d <dgraph.type> "Person" .
  }
}

Query the shortest path relying on Car and Bus.

{

 A as var(func: eq(name, "Alice7"))
 M as var(func: eq(name, "Mallory7"))

 sPathBus as shortest(from: uid(A), to: uid(M)) {  
  friend
  @facets(weightBus)
 }

 sPathCar as shortest(from: uid(A), to: uid(M)) {  
  friend
  @facets(weightCar)
 }  
  
 pathBus(func: uid(sPathBus)) {
   name   
 }
  
 pathCar(func: uid(sPathCar)) {
   name   
 }
}

Response contains the following paths conforming to weights specified.

    "pathBus": [
      {
        "name": "Alice7"
      },
      {
        "name": "Mallory7"
      }
    ],
    "pathCar": [
      {
        "name": "Alice7"
      },
      {
        "name": "Bob7"
      },
      {
        "name": "Tom7"
      },
      {
        "name": "Mallory7"
      }
    ]

Hey @anand, thank you for your reply.
Yes, later on I saw those docs about facets and tried rewriting my schema to use that instead. Looks good but I failed to mention that I’m trying to do this in Slash and it seems like DQL is not fully usable there - unless I write custom queries and declare them on the schema, is that right?

I see that some things from the example are not working (@index directive, { set { … } } queries do not run, for instance)

I’m trying to make it work and will reply again later. If you have any tips on how to accomplish that on
Slash let me know. thanks again!

We do have multiple ways to do DQL / GraphQL± with Slash GraphQL, either via the schema or you can just use any DQL or HTTP client. Please see https://dgraph.io/docs/slash-graphql/advanced-queries/ for more info.

Yes, I got it by activating the “flexible” backend mode and querying DQL by postman. Thank you!

1 Like