Ok. I’m 95% sure this is a bug, and I guess I should open an issue with the Core Dev, but I still consider myself a dgraph noob and I want to convince you first, Michel, because you’ve been so helpful all along.
Maybe this makes more sense with real data that makes sense, so how about this? We have users where their first name and last name are stored separately. Imagine we have two users, one called “Michel Beeson” and one called “Michel Conrad”. Now in dgraph, if we were to order only by first name, there’s no guarantee that Michel Beeson should appear before Michel Conrad. We would have to say “first, order by first name, and if the first name is the same, then order by last name”. So here’s a mutation that creates a bunch of users, who are either called “Michel” or “Susan”, but they have different surnames.
I will also add a predicate called “naturalOrder” which corresponds to the order that you would expect (ascending).
{
"set": [
{
"firstName": "Michel",
"lastName": "Antwerp",
"naturalOrder": 1
},
{
"firstName": "Michel",
"lastName": "Beeson",
"naturalOrder": 2
},
{
"firstName": "Michel",
"lastName": "Conrad",
"naturalOrder": 3
},
{
"firstName": "Michel",
"lastName": "Fittspatrick",
"naturalOrder": 4
},
{
"firstName": "Michel",
"lastName": "Wallace",
"naturalOrder": 5
},
{
"firstName": "Michel",
"lastName": "Zabala",
"naturalOrder": 6
},
{
"firstName": "Susan",
"lastName": "Button",
"naturalOrder": 7
},
{
"firstName": "Susan",
"lastName": "Dillan",
"naturalOrder": 8
},
{
"firstName": "Susan",
"lastName": "Grande",
"naturalOrder": 9
},
{
"firstName": "Susan",
"lastName": "Jackson",
"naturalOrder": 10
},
{
"firstName": "Susan",
"lastName": "Lawrence",
"naturalOrder": 11
},
{
"firstName": "Susan",
"lastName": "Palmer",
"naturalOrder": 12
},
{
"firstName": "Susan",
"lastName": "Ralley",
"naturalOrder": 13
},
{
"firstName": "Susan",
"lastName": "Trenton",
"naturalOrder": 14
}
]
}
Now I’m going to do some simple queries without pagination, just to be extra annoying and exhaustive. If I just do:
query {
users(func: has(firstName)) {
expand(_all_)
}
}
I get:
"data": {
"users": [
{
"lastName": "Beeson",
"naturalOrder": 2,
"firstName": "Michel"
},
{
"lastName": "Wallace",
"naturalOrder": 5,
"firstName": "Michel"
},
{
"lastName": "Button",
"naturalOrder": 7,
"firstName": "Susan"
},
{
"lastName": "Dillan",
"naturalOrder": 8,
"firstName": "Susan"
},
{
"lastName": "Conrad",
"naturalOrder": 3,
"firstName": "Michel"
},
{
"lastName": "Jackson",
"naturalOrder": 10,
"firstName": "Susan"
},
{
"lastName": "Trenton",
"naturalOrder": 14,
"firstName": "Susan"
},
{
"lastName": "Zabala",
"naturalOrder": 6,
"firstName": "Michel"
},
{
"lastName": "Grande",
"naturalOrder": 9,
"firstName": "Susan"
},
{
"lastName": "Lawrence",
"naturalOrder": 11,
"firstName": "Susan"
},
{
"lastName": "Antwerp",
"naturalOrder": 1,
"firstName": "Michel"
},
{
"lastName": "Fittspatrick",
"naturalOrder": 4,
"firstName": "Michel"
},
{
"lastName": "Palmer",
"naturalOrder": 12,
"firstName": "Susan"
},
{
"lastName": "Ralley",
"naturalOrder": 13,
"firstName": "Susan"
}
]
}
Totally random and as it should be. So lets sort by firstName descending:
query {
users(func: has(firstName), orderdesc: firstName) {
expand(_all_)
}
}
The results are:
"data": {
"users": [
{
"lastName": "Grande",
"naturalOrder": 9,
"firstName": "Susan",
"uid": "0x2724"
},
{
"lastName": "Palmer",
"naturalOrder": 12,
"firstName": "Susan",
"uid": "0x2728"
},
{
"lastName": "Button",
"naturalOrder": 7,
"firstName": "Susan",
"uid": "0x271e"
},
{
"lastName": "Dillan",
"naturalOrder": 8,
"firstName": "Susan",
"uid": "0x271f"
},
{
"lastName": "Lawrence",
"naturalOrder": 11,
"firstName": "Susan",
"uid": "0x2725"
},
{
"lastName": "Jackson",
"naturalOrder": 10,
"firstName": "Susan",
"uid": "0x2721"
},
{
"lastName": "Trenton",
"naturalOrder": 14,
"firstName": "Susan",
"uid": "0x2722"
},
{
"lastName": "Ralley",
"naturalOrder": 13,
"firstName": "Susan",
"uid": "0x2729"
},
{
"lastName": "Zabala",
"naturalOrder": 6,
"firstName": "Michel",
"uid": "0x2723"
},
{
"lastName": "Conrad",
"naturalOrder": 3,
"firstName": "Michel",
"uid": "0x2720"
},
{
"lastName": "Antwerp",
"naturalOrder": 1,
"firstName": "Michel",
"uid": "0x2726"
},
{
"lastName": "Fittspatrick",
"naturalOrder": 4,
"firstName": "Michel",
"uid": "0x2727"
},
{
"lastName": "Wallace",
"naturalOrder": 5,
"firstName": "Michel",
"uid": "0x271d"
},
{
"lastName": "Beeson",
"naturalOrder": 2,
"firstName": "Michel",
"uid": "0x271c"
}
]
}
Well we get the “Susans” before the “Michels”, but when it comes to their last names, the order is random. That’s not what we want. When the first names are the same, we want to sort by last name, so we use the following query:
query {
users(func: has(firstName), orderdesc: firstName, orderdesc: lastName) {
expand(_all_)
}
}
And we get the result:
"data": {
"users": [
{
"naturalOrder": 14,
"firstName": "Susan",
"lastName": "Trenton"
},
{
"naturalOrder": 13,
"firstName": "Susan",
"lastName": "Ralley"
},
{
"naturalOrder": 12,
"firstName": "Susan",
"lastName": "Palmer"
},
{
"naturalOrder": 11,
"firstName": "Susan",
"lastName": "Lawrence"
},
{
"naturalOrder": 10,
"firstName": "Susan",
"lastName": "Jackson"
},
{
"naturalOrder": 9,
"firstName": "Susan",
"lastName": "Grande"
},
{
"naturalOrder": 8,
"firstName": "Susan",
"lastName": "Dillan"
},
{
"naturalOrder": 7,
"firstName": "Susan",
"lastName": "Button"
},
{
"naturalOrder": 6,
"firstName": "Michel",
"lastName": "Zabala"
},
{
"naturalOrder": 5,
"firstName": "Michel",
"lastName": "Wallace"
},
{
"naturalOrder": 4,
"firstName": "Michel",
"lastName": "Fittspatrick"
},
{
"naturalOrder": 3,
"firstName": "Michel",
"lastName": "Conrad"
},
{
"naturalOrder": 2,
"firstName": "Michel",
"lastName": "Beeson"
},
{
"naturalOrder": 1,
"firstName": "Michel",
"lastName": "Antwerp"
}
]
}
Aha! Perfect ordering! This is exactly what I want. I want to emphasize that the ordering is not confused. Dgraph has it exactly right. The bug that I’m talking about is only an issue when it comes to pagination. So let’s try some pagination now. I won’t bother with “offset: 0” because then there is no problem. Let’s try this:
query {
users(func: has(firstName), orderdesc: firstName, orderdesc: lastName, offset: 3, first: 8) {
expand(_all_)
}
}
The results are:
"data": {
"users": [
{
"lastName": "Trenton",
"naturalOrder": 14,
"firstName": "Susan"
},
{
"lastName": "Ralley",
"naturalOrder": 13,
"firstName": "Susan"
},
{
"lastName": "Lawrence",
"naturalOrder": 11,
"firstName": "Susan"
},
{
"lastName": "Jackson",
"naturalOrder": 10,
"firstName": "Susan"
},
{
"lastName": "Dillan",
"naturalOrder": 8,
"firstName": "Susan"
},
{
"lastName": "Zabala",
"naturalOrder": 6,
"firstName": "Michel"
},
{
"lastName": "Wallace",
"naturalOrder": 5,
"firstName": "Michel"
},
{
"lastName": "Fittspatrick",
"naturalOrder": 4,
"firstName": "Michel"
}
]
}
What happened?! Exactly what I pointed out in earlier posts. Offset is discarding the first 3 results of “orderdesc: firstName” and ignoring the second order command. This is not an ordering issue; when I perform the query without pagination the order is correct. The problem is with offset.
Please try this with the dataset I have provided. You’ll see that the issue is real. Tomorrow I’ll happily open this as an issue with the Core Dev, just as soon as I figure out how to do that. But Michel, you’ve been a real super hero for me, so I feel it’s only right that I get you on my side.