How to find nodes with a scalar predicate having values found during traversal

Let’s say I have following schema -

user.name: string
user.block: uid @reverse

block.name: string
block.category: string
block.city: uid @reverse

city.name: string

Now given a user.name, I need to find all users of same city and same block category.

{
  getOtherUsers(func: eq(user.name, "Siddharth")) {
    user.block {
      block.category # C
      block.city {
        ~block.city { # Here I need to find only those block with categoryc C

        }
      }
    }
  }
}

Not sure, but maybe something similar to this:


{
  var(func: eq(user.name, "Siddharth")) {
    user.block {
    cat as  block.category
    city as block.city
    }
  }
    var(func: uid(city)) {
    ~block.city @filter(uid(cat){
      ~user.block{
       users as uid
     }
   }
 }
  getOtherUsers(func: uid(users)) {
    uid
    user.name
  }
}

Does @filter() work without any function?
Also I don’t think we can use eq() filter over value variables directly. According to docs we can use val(variable) but then it works only in the context of enclosing uid.

In this case I want to search for all blocks which has category predicate same as user → block → category.

No sure about the question, everything you put inside a filter is a function.

You’re right, I created a quick head example. I forgot the syntax details. It’s fixed.

So that I can give you something similar to its structure, you need to provide a valid example (a mutation, to follow your train of thought). What I could do is spend some time creating something similar, but functional. However, you would have to analyze what I created and apply to your model.

Here in the Discuss you have several examples and gists of similar situations.

PS. The approach is similar to this Get started with Dgraph


{
  var(func: allofterms(name@en, "Taraji Henson")) {
    actor.film {
      F as performance.film {
        G as genre
      }
    }
  }

  Taraji_films_by_genre(func: uid(G)) {
    genre_name : name@en
    films : ~genre @filter(uid(F)) {
      film_name : name@en
    }
  }
}

Cheers.

@MichelDiz Will look into docs examples and see if examples suffice. Else will come up with examples along with mutations. Thanks

1 Like

@MichelDiz Thanks. Your suggestion helped me. Hopefully I am on right track now.

I have a scenario where a value variable is not initialized and if it is used later db throws an error. Here is an example -

curl localhost:8080/query -XPOST -d '
{
  steve as var(func: allofterms(name@en, "Stesven")) {
    director.film {
      fn as name@en
    }
  }

  stevens(func: uid(steve)) {
    director.film @filter(eq(name@en, val(fn))){
      name@.
    }
  }
}' | python -m json.tool | less

Output

{
  "errors": [
    {
      "code": "ErrorInvalidRequest",
      "message": ": No value found for value variable \"fn\""
    }
  ],
  "data": null
}

How should we handle this scenario. It seems variable fn is not defined in this case.

If I place val() as first argument to eq() function it works great. Is there any reason it behaves this way? @MichelDiz

Not sure, it’s curious.

Should I go ahead and file a bug?

Can you show what you did, your answer confused me a bit.

Running following query on play dgraph instance will have an error output as mentioned below.

curl localhost:8080/query -XPOST -d '
{
  steve as var(func: allofterms(name@en, "Stesven")) {
    director.film {
      fn as name@en
    }
  }

  stevens(func: uid(steve)) {
    director.film @filter(eq(name@en, val(fn))){
      name@.
    }
  }
}' | python -m json.tool | less
{
  "errors": [
    {
      "code": "ErrorInvalidRequest",
      "message": ": No value found for value variable \"fn\""
    }
  ],
  "data": null
}

Whereas if I keep val(fn) in @filter clause as the first argument of eq() it works fine. Is this behaviour intended?

You said you got it (That worked), wanted to see how you got it. What you just wrote has already been said.

This query works without any error.

curl localhost:8080/query -XPOST -d '
{
  steve as var(func: allofterms(name@en, "Stesven")) {
    director.film {
      fn as name@en
    }
  }

  stevens(func: uid(steve)) {
    director.film @filter(eq(val(fn), name)){
      name@.
    }
  }
}' | python -m json.tool | less

Thanks, but not working at my side oO

I am getting empty response

{"data":{"stevens":[]},"extensions":{"server_latency":{"parsing_ns":27586,"processing_ns":2413021,"encoding_ns":658122},"txn":{"start_ts":71560}}}

no errors. Compare it to response of earlier query.

What are you getting?

Only “Your query did not return any results”.

BTW, if it returns empty, does not mean it was a success.

This use to me seems unexpected, so it confused me. I was hoping you’d get me something back. And not empty response. You see?

The right usage in this case with “value” is like this:

{
  steve as var(func: allofterms(name@en, "Steven")) {
    director.film {
      fn as name@en
    }
  }

  stevens(func: uid(steve)) {
    director.film @filter(eq(val(fn), "Into the Wind")){
      uid
      name@.
    }
  }
}

Response


{
  "data": {
    "stevens": [
      {
        "director.film": [
          {
            "uid": "0x3de19",
            "name@.": "Into the Wind"
          }
        ],
        "uid": "0x31ce2"
      }
    ]
  }

Ok. Let me be more clear.
I got the above json by checking http response.

Empty response is different than error response. If it is empty response I can further use the response in other query blocks.
If there is error response, other query blocks fail to execute.

Check the answer above.

Dgraph will only return error if there was syntax error or from the server. And not usage error. In my answer above you can see the correct way to use this approach.