Whats the DQL equivilant of GQL's "has" filter

https://dgraph.io/docs/graphql/queries/search-filtering/#filter-for-objects-with-specified-non-null-fields-using-has

When filtering an edge, how do I exclude edges who’s subsequent node has a specific predicate defined? For example:

<replies>: [uid] .
<replyTo>: [uid] .
<comments>: [uid] .
<post>: uid .

type Comment {
  post
  replies
  replyTo
}

type Post {
  comments
}

I want to get a Post, and then all of its comments, and then all of the replies to each comment. This is what I have currently:

{
  _allComments as var(func: type(Comment))

  post(func: type(Post)) {
    uid
    comments @filter(not uid_in(replyTo, uid(_allComments))){
      uid
      replies {
        uid
        comments {
          uid
        }
      }
    }
  }
}

But I’m worried about how it will perform at scale. What if I have 1M comments, does that mean that _allComments will have to load in every single comment uid? Or does dgraph have some set-theory based optmization that means that this is the correct way to check for null?

1 Like

Hi @danhab99
Could you please explain the result that you are looking for with an example? This looks like a doable thing

1 Like

DQL also has the has function (https://dgraph.io/docs/query-language/functions/#has), you might also want to look at the cascade directive (https://dgraph.io/docs/query-language/cascade-directive/).

1 Like

So to recap:

  • A post can have many comments
  • A comment is related to 1 post
  • A comment can have 0 to many reply comments

I want to query dgraph for a post and all its related comments formatted in a tree structure. Right now I can get a post all of its edges to its comments. I want to filter all the edges between a post and a comment to exclude all comment’s who’s replyTo edge is null. Then I will use the comments “replies” edge to follow each comment thread.

@vinum I’m awayre of the has function but it doesn’t do the same thing is the GQL has filter. The has function includes all nodes who’s type includes a predicate, but it doesn’t check for null values. I need to filter if an edge is null.

1 Like

When using you are using cascade then it automatically filters the results that are null. If a comment does not have replyTo it should not appear in results.

1 Like

Oh I made a mistake when explaining myself! Hang on…

If a comment does not have replyTo it should not appear in results.

Right I want the opposite of that. If and only if a comment does NOT HAVE its replyTo defined than include it in the results.

How do I do that?

{
  post(func: type(Post)) {
    uid
    comments @filter(NOT has(repliyTo)) {
      uid
      replies {
        uid
        comments {
          uid
        }
     replyTo {
         uid
      }
      }
    }
  }
}
1 Like

Sry for late reply.

comments @filter(NOT has(repliyTo)) {

See that’s why I posted this thread, the has function isn’t checking if replyTo is null. I want only nodes of type Comment who’s replyTo predicate is null.

Look into @cascade

J

Maybe fix the typo and this will work??

Hey everyone, just wanted to announce that I figured it out. It goes like this:

{
  posts(func: type(Post)) {
    uid
    comments @filter(eq(count(replyTo), 0)) {
      uid
      replies {
        uid
      }
    }
  }
}

So eq(count(replyTo), 0) was what I was looking for. Though I feel like we should have a null checking function, or an inverse cascade (not sure how it would work)? Oh well, problem solved.

Thanks all!