More graceful way to pass dynamic value to UID_IN


(Jeff Hull) #1

Hi All,

I’m struggling to find a graceful way to accomplish the following. I need to use the UID_IN function with dynamic input. Per the docs, UID_IN can take only a UID literal rather than a variable.

When running queries, I need to filter to a subgraph based on user permissions and user selected filters. So I would like to run:

var(func: uid([USER UID])) {
      validNs as HasAccessToNamespace
      filteredNs as FiltersOutNamespace
    }

results(func: eq(VertexType, "Entity")) @filter(UID_IN(Namespace, uid(validNs)) and NOT UID_IN(Namespace, (filteredns))) {
....
}

Currently, I have to run two dgraph queries…one to get validNs and filteredNs so that I can build a string of form:

@filter(UID_IN(Namespace, [UID1]) and UID_IN(Namespace, [UID2]) ... and UID_IN(Namespace, UIDn))

To then concatenate into the second query.

This seems unnecessary because the first query should resolve before the 2nd runs, meaning that when the second query runs, the input to UID_IN can be treated as constant values? Maybe there is a better way to do this that I’m not thinking of?


(Pawan Rawal) #2

Hey @tamethecomplex, try the query below instead

{
  var(func: uid(USER_UID)) {
    validNs as HasAccessToNamespace
    filteredNs as FiltersOutNamespace
  }

  results(func: eq(VertexType, "Entity")) @cascade {
    ...
    Namespace @filter(not uid(filteredNs) and uid(validNs))
  }
}

(Jeff Hull) #3

Thanks @pawan, this almost gets me there. The one issue is in this scenario I cannot guarantee that all of the other predicates I am returning in the results() block will be present, which in this case, using @cascade, would cause that entire result to fall out of the query, right? Not a huge deal as I can probably code around this to make sure all other attributes are present…but might be nice to be able to exclude certain predicates from the @cascade treatment.


(Pawan Rawal) #4

You can request the _uid_ as that is guaranteed to be present, so then Entities which have both a _uid_ and len(Namespace) > 0 would be returned. Does that work for you?


(Jeff Hull) #5

To make sure I understand…If I run this modified query:

{
  var(func: uid(USER_UID)) {
    validNs as HasAccessToNamespace
    filteredNs as FiltersOutNamespace
  }

  results(func: eq(VertexType, "Entity")) @cascade {
    uid: _uid_
    name
    description
    externalId
    Namespace @filter(not uid(filteredNs) and uid(validNs))
  }
}

If externalId is missing for a result, but all other attributes are present, would that result still be excluded by @cascade due to a missing externalId?


(Pawan Rawal) #6

Yes if external id is missing for an entity it would be missing from the result. Basically, all children should have some value/uids for it to present in the result. You can get around that by using another query block if you like.

  filteredResults as var(func: eq(VertexType, "Entity")) @cascade {
    uid: _uid_
    Namespace @filter(not uid(filteredNs) and uid(validNs))
  }

  results(func: uid(filteredResults)) {
    ...
    # All that you want to retrieve here.
  }

(Jeff Hull) #7

Ah, this is exactly the solution I needed. Thanks!!


(Jeff Hull) #8

For anyone else looking for a solution, here’s the final query:

var(func: uid([USER UID])) {
      validNs as HasAccessToNamespace
      filteredNs as FiltersOutNamespace
    }

filteredResults as var(func: eq(VertexType, "Entity")) @cascade {
    uid: _uid_
    Namespace @filter(not uid(filteredNs) and uid(validNs))
  }

finalResults(func: uid(filteredResults)) {
    ...
    # All that you want to retrieve here.
  }

(system) #9

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.