Custom Digging function

Question / Feature Request

Custom Digging function

What you actually did

Declarative GraphQL, but for my needs I need imperative code logic

What you wanted to do

Is it possible to implement custom “digging” function for Dgraph ?
I mean for my needs I have to write a custom function for BFS traversal of graph, it should decide what type of nodes it should dig into, on edge attributes, how many layers, etc.

It will be good to have plugin interface in Go to write functions like that.

Hi @fly

Do you have any concrete examples? Perhaps there might be a feature you are missing? (like @recurse())

If you could provide an example, perhaps with some demo data, I can try to help further.

Hi @chewxy

Thanks for replying

I have dig function in Go for BFS traversal of graph, there is a pseudo-Go code of it:

	// Return value:
	// 		positive number to continue digging of certain node
	// 		0 to skip digging of node
	//    negative number to stop BFS
	diggerFunc := func(edge *Edge, current, neighborNode *Node, depth int) int {
		cycles++
		if depth > MaxDigDepth || cycles > maxDigCycles {
			return -1 // stop now
		}
		if cycles > 500 && time.Since(startedAt) > maxDigDuration {
			return -1 // stop now
		}

		// Some skip 
		if edge.SourceID == userNodeID {
			return 0 // skip
		}

		// Some skip 
		if depth > 3 && neighbor.Type() == SomeType {
			return 0 // skip
		}

		// Skip based on depth and Edge time attribute 
		if edge.LastSeenAt < DepthTimeCoef * depth + SomeDynamicTimepoint  {
			return 0 // skip
		}

		// Skip based on depth and Edge time attribute 
		if depth > 5 && edge.LastSeenAt < SomeOtherDynamicTimepoint {
			return 0 // skip
		}

		// skip minor neighbors of neighbors
		if depth > maxDigDepthMinorNodes {
			if neighbor.Type() == types.TypeA || neighbor.Type() == types.TypeB || || neighbor.Type() == types.TypeC {
				return 0 // skip
			}
		}

		// skip on edge weight dependent of depth
		if edge.GetWeight() < 5.0 * depth {
			return 0 // skip edges with low weight
		}

		// continue traversal
		return 1
	}

In my case I have to write some business logic inside digger function which is difficult implement in declarative form.

Let me file this as a feature request. In the meantime, I think we have query experts that will help you write your query. Might be worth an ask.

From a cursory look, it appears that you can write a @recurse(loop:500) directive that will do that. I’ll look into it closer tomorrow arvo.

Thank you.
loop:500 does not work here - that is just start point where I check for work time limit.

I am really doubt it is possible to describe logic like that (with dynamic conditions) in
Recurse Query
I my real business logic case that function look much complex.

I do something like that.

{
        var(func: type(Human)){
    	u as uid
    	v as graph(
      	pagerank(
		  edges:[follow]
		))
  	    }
  	
      q(func: uid(u)){
    	uid
    	val(v)
        }

}

In the part v as graph( pagerank( edges:[follow] )) ,it’s a go plugin add to dgraph alpha.
It need modify the source of dgraph gql parser, and develop your own algo plugin.

1 Like

Yep, looks like current Dgraph does not allow what I want. And patching is required.

@chewxy Hi. Did you have a chance to look ?