Sort and page an edge before filtering it

I’m trying to find a time entry based on the time of the earliest connected time entry segment.

Here’s the query I’m writing.

timeEntries as var(func: type(TimeEntry)) @cascade {
  owner @filter(uid($ownerUid))
  segments (orderasc: startTime) (first: 1) @filter(ge(startTime, $start) AND le(startTime, $end))
}

It seems that filtering always is processed first, then sorting and paging. Is there a way to page this query before filtering it?

That makes sense. Is there a reason why you would want to page then filter?

To help you understand why filter is done before paging, let’s look at a list of numbers. We want to page every 3 numbers, and we want to filter any number that is bigger than 5.

filter then paginate

Here’s the list of numbers:

1 2 6 5 2 5 2 3 6 3 8 7 8 7 2 1 2 6

Here’s what happens when we filter the list so that we keep any number that is smaller than or equal to 5:

1 2 5 2 5 2 3 3 2 1 2

And now we page it every 3 numbers:

1 2 5 | 2 5 2 | 3 3 2 | 1 2

paginate first then filter

Here’s the list of numbers:

1 2 6 5 2 5 2 3 6 3 8 7 8 7 2 1 2 6

Here’s what happens if we page them, 3 at a time:

1 2 6  | 5 2 5  | 2 3 6 |  3 8 7  | 8 7 2 | 1 2 6

And now we filter it:

1 2 _  | 5 2 5  | 2 3 _ |  3 _ _ | _ _ 2 | 1 2 _

I filled in the removed numbers with an _.

Now we have to do work to move the numbers around from the page - this costs an additional 6 move operations.

Now I can see why if you only want to filter the results of the first page, you might want to page first then filter. In that case, you can do something like this:

var(func: type(TimeEntry)) @cascade {
  owner @filter(uid($ownerUid))
  S as segments (orderasc: startTime) (first: 1) 
}
segments as var(func: uid(S)) @filter(ge(startTime, $start) AND le(startTime, $end)) {
 ....
}

would do the trick I believe