DQL Feature Request: Client Side optimization for edge UID fetches

I cannot get the UID of an edge predicate, if I don’t expand the query with brackets.

This hurts in two ways:

  1. More complicated query preparation for single UID fetch.
  2. Client side should create an extra object to retrieve a single UID. (Unnecessary memory and code)

In the following example scenario, I would like to get UID instead of NOTHING.

If we get UID in such queries this is a great benefit for client side code.
As a result, client doesn’t have to create an object for just getting an UID string.

For example:

type post {

parent: uid .
text: string .

query(func: has(parent)) 

Expected response:

  "data": {
    "query": [{ "parent": "0x7" }]

It is important to get UID as a string property but not a sub object.
This leads a client side optimization.

If we send a query by explicitly telling to expand the edge current behaviour is perfect.

query(func: has(parent-post)) 

Then response would be as is:

  "data": {
    "query": [{
			"uid": "0x7"

Try this out

  var(func: has(parent)) {
    PAR as parent
  query(func: uid(PAR)) {
    parent : uid

This example makes query more complicated. Expanding brackets even better than this approach.
I believe my suggestion is easy to develop and I don’t see any cons.
Do you agree?

Okay, let’s go part by part.

Edges don’t have UIDs. Only nodes/entity has.

That’s how the query lang works.

That could be solved in another way. Using normalize.

query(func: has(parent)) @normalize {
	parent {
		parent : uid

I don’t see it like that. Actually, the only difference is that we break it into two query blocks. I was just trying to give you a way to return the response in the format you have shown in the example. The normalize approach also gives the same result.

PS. It is not possible to return a UID without expanding the nested blocks.

1 Like

Outgoing edges are associated with UIDs. Internally every edge contains none,one or multiple UIDs.

You have shown multiple ways of getting the UID and I am ok with that.

My suggestion is more straight forward way of getting edge’s associated UID.
No additional workarounds needed.
Just write the edge name without brackets and get the associated UID or UIDs in the response.

Yes, they have a list of UIDs or a single UID. But it doesn’t belong to that edge. It is just a “pointer”, the UID will be always part of the entity. In that sense, the language is a bit strict. It would be hard to tell what the user wants without the user being explicit in the query.

There are other workarounds like recurse, expand(all) too.

I know it is kind of odd when we start with DQL or GraphQL. But you get used to it soon. It will be very intuitive.

1 Like

Thank you Michel for awesome suggestions with multiple ways. They are precious.

I think feature requests should not be shutdown immediately with 1 person’s decision.
We might list pros and cons, discuss. Also we might see what other users think about.

I mentioned 2 cons of not having the proposed feature.
1- additional code for simple UID fetches (workarounds still require additional code for generation of the query)
2- additional objects consuming memory both on client side and server side.

I don’t see any cons as of now.

I think I see the ask.

When you study the language you see that these two following queries are in essence equal:

var(func: has(parent)) { parents as parent }
q(func: uid(parents)) { uid }
var(func: has(parent)) { parent { parents as uid } }
q(func: uid(parents) { uid }

And seeing that both of these variables parents seem to produce the same results when put in a uid function, it would make sense if they returned the same data when queried, but that is not the case.

However, the reasoning is that DQL implemented variable blocks that were out of the GraphQL spec that DQL was designed to initially follow, it still follows the spec when expanding a node by only returning the uid if it is specifically requested in the expanded node on the edge.

So while I understand the ask, I think there is no ROI from an engineering viewpoint. So it saves a very small amount of code (5 characters to be exact) {uid}, but does this really deem a need to invest in changing a core aspect of the DQL query language.

Sorry, but I agree with @MichelDiz here, best to cut this off early. No sense getting your hopes up here.

Actually, I do think @koculu might have a point. I very often want to just pull out the structure of the graph. To do so I only care about the names of the predicates and the UIDs.

This is so I can map the graph structure onto a data structure in my local program and then perform some graph algorithm on it.

@koculu what are you pulling out UIDs for if I may ask?

Hi @chewxy

Really basic and common scenario:

  • I have types: profile and post
  • Each profile associated with posts
  • I want to show posts along with profile title, avatar etc in one page
  • to do so: I do a query to the post nodes.
  • it is very tempting to get profile information with single query for developer.
  • however it is not good in terms of putting duplicated meta data reading burden on Dgraph servers.
  • hence, it is wise to get just profile uids associated with posts.
  • after that I can get profile meta data with those uids in an additional query to Dgraph server.
  • If I retrieve 1000 posts out of 10 profiles, in this way I can ask Dgraph server 10 profile meta data reads but not 1000.

In this very basic and most common scenario because fetching the UIDS requires expanding brackets,
I had to parse a JSON object to get a string UID and then I mapped that into another C# object.
Extra code, extra condition, extra object.

I am fine with my current approach. It is not a big deal. Created the object. Parsed the inner JSON object etc.
On the other hand I strongly believe it is nice to have feature for me as a developer.