Find all inbound outbound edges

Hi there.

How can I find out all edges in and out bound to an vertice?

Take it for example if have a “contact_person” vertice which can be bound to and from any node using an arbitrary number of “edge types” like “know”, “known_by”, “employee_of”, “has_purchased”, etc…, and such relations could not be predicted whether they exists or not beforehand.

Now I have “joe” and “mary” as “contact_person” each one with a dynamic number of edges.

How do I do to find out what edges each one have, in and out bound do it?

Thanks!

1 Like

Not sure I fully understand the question but using the @reverse directive in the schema for these edges, you can then use ~ in front of the field name to see inbound edges.

query {
    hey(func: uid(JOEUID)) {
        known_by { ... }
        ~known_by { ... }
    }
}

In the first known_by it says JOE is known by { xyz }, the second one means JOE knows… That way, you do not need knownBy and knows edges.

Hi. Thanks for your response, but no, this is not what I need.

I do not know how many, and how are the edges that a specific node may have, and thats what I need to discover.

Much like the “_predicate_” directive I would need a “_edges_” one, or maybe a set of “_edges_”, “_inbound_edges_” and “_outbound_edges_” to retrieve all edges of a node or only those in one direction.

Doesn’t expand(all) { expand(all) } do the trick?

No. It doesnt. Imagine that given an uid, you need now to list all edges point to and from it, along with its “names”.

The concept of Edges is “Subject, Predicate, Object, Label”. In this case “expand (all)” would be the correct one to locate all Edges and their relationships.
Combining with “~ reversedEdge” and Subs “expand (all) {expand (all)}”.

If you want to list predicates. Just _predicate_ can do this like for example:

{
  director(func: eq(name@en, "Geoffrey Rush")) {
    _predicate_
    actor.film {
      _predicate_
  ~maybeReversed {
      _predicate_
      }
    }
  }
}

Do the following. Build a mutation close to what the model you want, and then build a supposed response you want to receive. To understand better.

Hi. Thanks for your responses, but I think you are not getting my point.

Proposal: I have a node uid 0x01 that has some (maybe one, maybe fifty) relationships with other nodes. I do not know how many, and I do not know to which other nodes.

Problem: Build a list with the names of each relationship the node 0x01 has.

Obs 1: I dont care about the other nodes, only about the edges.
Obs 2: It does not need to go deep, only direct edges will suffice.

So you want to expand only predicates that have a relationship. It is? I do not think Dgraph has a filter for that.

At least you need to know them all.

You can use inverse Expand (all). In theory you should already know which predicates that generate relationships (all of possible ones). So you can build a query with all possible predicates. What does not expand is because there is no relation. The Dgraph will not return Edges that has no reaction.

{
  director (func: eq (name @ en, "Geoffrey Rush")) {

   ~ friendOf {
            expand (_all_)
  }
   ~ OnwnerOf {
            expand (_all_)
  }
   ~ DirectorOf {
            expand (_all_)
  }
   ~ PresidentOf {
            expand (_all_)
  }
}

All predicate must exist @reverse, and not all of them will expand if they do not exist. Now if you want to create lists you can do this: (Just an idea)

{
 var (func: uid (0x1)) {

   ~ friendOf {
            friend as uid # name
  }
   ~ OnwnerOf {
            Objetc as uid # name
  }
   ~ DirectorOf {
            Film as uid # film.name
  }
   ~ PresidentOf {
            Company as uid # Company.name
  }

myList1 (func: uid (friend)) {
name
}
myList3 (func: uid (Objetc)) {
name
}
myList4 (func: uid (Movie)) {
film.name
}
myList5 (func: uid (Company)) {
Company.name
}
}

Some of these lists will come empty if relations do not exist. If not, give some more details as I said above.

Take a lonk on this https://docs.dgraph.io/query-language#expand-predicates

I know it’s not related

{
  var(func: eq(name@en, "Lost in Translation")) {
    pred as _predicate_
    # expand(_all_) { expand(_all_)}
  }

  director(func: eq(name@en, "Lost in Translation")) {
    name@.
    expand(val(pred)) {
      expand(_all_)
    }
  }
}
1 Like

Well, I’ll do some tests here but I think its a bump.

For one hand I have the power to relate any piece of information to every other to my heart contents.

Then I can freely create new relationships without the hassle of creating M:N tables and doing insane JOINS (SQL).

But when it comes to get back the info stored, I just cant. For dynamic structural data systems this kind of feature is a must. And the info stored as inferred relationships, which is often lost or hard to get on a SQL db is exactly the power one seeks in a graph database, after all.

Some parts of DGraph seems in a “almost” state to me. I mean, if you do all your queries by hand and know exactly what you have, its ok, but when you go more “dynamic” with things it falls short.

I do think that implementing those _edges_ directives should’nt be that hard and it would be a great tool.

Thanks, I’ll report after the tests.

1 Like

Actually, this do explode all my data to me:

{
    q(func: has(__is_users)) {
        expand(_all_) { 
          expand(_all_) {
            expand(_all_) {
              expand(_all_)
            }
          }
        } 
    }
}

But, as in my question about uids, this left to me the work to parse all trough the data, when I could had received just the plain edge list for each __is_user in the query.

Did not solved my question, but its a starting point.

Just to make it clear, this query:

{
    q(func: has(__is_users)) {
	    _predicate_
    }
}

Returns me this:

{
  "data": {
    "q": [
      {
        "_predicate_": [
          "_updated_uid",
          "_created_uid",
          "user",
          "pessoas",
          "_created_time",
          "confirm",
          "_created_by",
          "__is_users",
          "pwd",
          "_updated_by",
          "_updated_time"
        ]
      }
    ]
  },
  ...

Ok, thats good. So, please let this query:

{
    q(func: has(__is_users)) {
	    _edges_
    }
}

Return me this:

{
  "data": {
    "q": [
      {
        "uid": 0x1
        "_edges_": [
          "knows",
          "employee_of",
          "friend_of"
        ]
      },
      {
        "uid": 0x2
        "_edges_": [
          "knows",
          "son_of",
          "married_with",
          "employee_of"
       ]
      }
    ]
  },

expand (all) I think it’s very unplanned (result too variable.), I find it much better to develop solid query patterns. Let it expanding out everything. This way you create unforeseen JSON formats. Not every application would know how to handle it dynamically.

I would recommend expand (all) only to explore relationships between nodes still in the planning stage.

I do not know, I think if the DB Dgraph administrator knows how to plans well, he does not need features like that. Creates an entire directive just to know when a Node has relations with other nodes through Edges seems to me a wasted time. Being that you can create a simple pattern on your application.

Dgraph was created inspired by GraphQL. There are no such things in GraphQL (not that I know of, after all GraphQL is not a DB.), everything is solved internally in GraphQL for DBs.

If you demonstrate real usability convincing the Engineers and defend(uphold) it as a feature. Who knows. Maybe it’s not complicated to do in a short time, could be a “filter” for the directive predicate like:

  _predicate_ @filter (has (uid)) # would return predicates that have relations only.
  _predicate_ @filter (has (int))
  _predicate_ @filter (has (string))

See (the rodamap link) there are many features to come out yet for Dgraph. In the short term I do not know if your need would come easy.

But it is right there my point: you are not considering that a beast like DGraph allows you to create some really nifty sneaky clever dynamic apps, with possibilities of grow much beyond regular SQL based systems.

I could PLAN an app to happily work with NON beforehand PLANNED relationships. If only I had a little more info, or access, or control whatever, over my lets say, metadata. Intelligent apps, growing with the user, and evolving as its been used, thats what I’m talking about and thats why I’m “here”.

Now, this DO include the need of a really smart planing of your schema and data, but goes much beyond that. You’ll need to build logic that needs be able to figure your metadata out on the fly.

DGraph, please: think dynamic, show me the meta. =]

Thanks.

2 Likes

P.S: predicate filter is nice, but I dont think it could deliver what inbound_edges and outbound_edges could. Why not have both? =]

1 Like

But if you expand(_all_) then unless you use arrays of scalar values in your schema, if you find an array for a given predicate, it is an edge pointing to n other nodes. And if your source node doesn’t have relationship “relatesTo”, then it wouldn’t appear.

If you use arrays of scalars, then ignore the above as an array for a given JSON field could be either an array of nodes, or an array of strings, integers, etc. And if your do not know in advance, then you are unable to filter out upon receiving the JSON result.