Filters in GraphQL

Let’s confirm that. Because, we’re still in the same pattern, same depth as the query, and response is in the same shape. What are you referring to?

Actually, thinking more about this, I feel this is no different than having edges, which don’t produce results. With that understanding, I think this would be within the realms of GraphQL.

We can try and get someone’s advice on this. Someone from GraphQL team.

What I meant was:

{
  me(_uid_: 0x01) {
    friends (first: 10) {
      filter {  // intersection between 2 conditions defined within.
        type.object.name.en (anyof: ["john", "snow"])
        born.on (ge: 1990, lt: 2000)
      }
    }
  }
}

Here filter, though is a keyword for us, is similar to a predicate for someone who just knows GraphQL. And there wont be a field called filter in the JSON response that he gets.

Isn’t that our current behavior, if filter as predicate has no result?

But, if filter predicate has no result, what would the subsequent levels (children of filter) act on? In case of the example, the type.object.name.en and born.on would have no source nodes (query field in subgraph will be empty for evey child of filter predicate).

{
  me(_uid_: 0x01) {
    friends (first: 10) {
      filter {  // intersection between 2 conditions defined within.
        type.object.name.en (anyof: ["john", "snow"])
      }
    }
  }
}

so to access the name of my frineds in the JSON response. I’ll do
resp[“me”][“friends”][“filter”][“type…”], but when we reach the filter level it’ll be empty and we can’t access the type.object.name…

We discussed this. So, just to close the loop on this one, the query that you mentioned there, doesn’t ask for any field inside friends (only filters on that), and hence, it would be empty.

So, something like this might be closer to GraphQL syntax. What do you guys think?

{
  me(_uid_: 0x01) {
    friends (first: 10) @filter(
        anyOf("type.object.name.en", "john", "snow")
        ge("born.on", 1990)
        lt("born.on", 2000) )
        @filter(gt(_count_(child), 2)) {

      relatives @filter (near("home.geolocation", {lat: 12.43, lon: -53.211, rad: 10k}) {
        name
      }
    }
  }
}

Or, we could do something like this:

{
  me(_uid_: 0x01) {
    friends (first: 10) @filter(
        (anyOf("type.object.name.en", "john", "snow") &&
        ge("born.on", 1990) && lt("born.on", 2000)) || gt(_count_(child), 2)) {

      relatives @filter(near("home.geolocation", 12.43, -53.211, 10)) {
        name
      }
    }
  }
}

Adding another one below just for completeness sake, but I find this format dirty because we’re treating predicates like variables (which they are not), but yet can’t fully cover all the cases (like anyOf, or near).

{
  me(_uid_: 0x01) {
    friends (first: 10) @filter(
        (anyOf("type.object.name.en", "john", "snow") &&
        "born.on" >= 1990 && "born.on" < 2000) || _count_(child) > 2) {

      relatives @filter(near("home.geolocation", 12.43, -53.211, 10)) {
        name
      }
    }
  }
}

Alright! Would love some advice now, @minions.

@mrjn Could you update the example so that it also requests the appropriate fields(predicates within friends or relatives). As I understand right now the above queries don’t request anything.

Would it be like this? If yes then the third one looks best(its not as verbose as the first, uses && , || , ge , lt)

{
  me(_uid_: 0x01) {
    friends (first: 10) @filter(
        (anyOf("type.object.name.en", "john", "snow") &&
        ge("born.on", 1990) && lt("born.on", 2000)) || gt(_count_(child), 2)) {

      type.object.name.en
      born.on
      relatives @filter(near("home.geolocation", 12.43, -53.211, 10)) {
        name
      }
    }
  }
}
1 Like

They do request the relatives of the friends, and the names of those relatives. Also, note that you don’t necessarily have to request the same predicates as you use in the filter. You could, but you don’t have to.

I feel that if you have && ||, people might expect = < >?

I think they might initially, but they will get used to it pretty fast. If we have a cleaner way to give them all those special character ops, we could consider them; but I can’t think of any. The one I propose above (the last one) is more on the lines of we shouldn’t do this.

I feel this

{
  me(_uid_: 0x01) {
    friends (first: 10) @filter(
        anyOf("type.object.name.en", "john", "snow")
        ge("born.on", 1990)
        lt("born.on", 2000) )
        @filter(gt(_count_(child), 2)) {

      relatives @filter (near("home.geolocation", {lat: 12.43, lon: -53.211, rad: 10k}) {
        name
      }
    }
  }
}

looks pretty good and also close to GraphQL as we discussed the other day. Just using @filter on the parent level compared to _filter_ in the previous design.

Wonder if we have come to a conclusion on this?

The work on query, string matching is blocked by this. (I will work on tokenizer and other stuff while I wait for this to be resolved.)

To unblock, we don’t have to fully resolve the design. All I need to know is whether how exact matching looks like. Will it look like @filter or filter {}. Something very simple for exact matching would suffice for me, at this point. Thanks.

Let’s go with this one. It ensures there’s only one filter directive, while also providing boolean functions and a way to connect them together via ANDs, ORs and brackets.

In this syntax how would you type the query:

Find all films with genre “Musical drama” where the actor is “Angelina Jolie”

Umm yeah, multi level fiters would be required. One way would be:

{
  debug(_xid_: <angelina-joulie>) {
    film.actor.film {
      film.performance.film @filter( {
      film.film.genre @filter ( equal(type.object.name.en, "Musical drama"  )
    })
      {
        type.object.name.en
      }
    }
  }
}

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