I'm trying to efficiently find the top entries by group in Arango (AQL). I have a fairly standard object collection and an edge collection representing Departments and Employees in that department.
Example purpose: Find the top 2 employees in each department by most years of experience.
Sample Data:
"departments" is an object collection. Here are some entries:
| _id | name |
|---|---|
| departments/1 | engineering |
| departments/2 | sales |
"dept_emp_edges" is an edge collection connecting departments and employee objects by ids.
| _id | _from | _to | years_exp |
|---|---|---|---|
| dept_emp_edges/1 | departments/1 | employees/1 | 3 |
| dept_emp_edges/2 | departments/1 | employees/2 | 4 |
| dept_emp_edges/3 | departments/1 | employees/3 | 5 |
| dept_emp_edges/4 | departments/2 | employees/1 | 6 |
I would like to end up with the top 2 employees per department by most years experience:
| department | employee | years_exp |
|---|---|---|
| departments/1 | employee/3 | 5 |
| departments/1 | employee/2 | 4 |
| departments/2 | employee/1 | 6 |
Long Working Query
The following query works! But is a bit slow on larger tables and feels inefficient.
FOR dept IN departments
LET top2earners = (
FOR dep_emp_edge IN dept_emp_edges
FILTER dep_emp_edge._from == dept._id
SORT dep_emp_edge.years_exp DESC
LIMIT 2
RETURN {'department': dep_emp_edge._from,
'employee': dep_emp_edge._to,
'years_exp': dep_emp_edge.years_exp}
)
FOR row in top2earners
return {'department': dep_emp_edge._from,
'employee': dep_emp_edge._to,
'years_exp': dep_emp_edge.years_exp}
I don't like this because there is 3 loops in here and feels rather inefficient.
Short Query
However, I tried to write:
FOR dept IN departments
FOR dep_emp_edge IN dept_emp_edges
FILTER dep_emp_edge._from == dept._id
SORT dep_emp_edge.years_exp DESC
LIMIT 2
RETURN {'department': dep_emp_edge._from,
'employee': dep_emp_edge._to,
'years_exp': dep_emp_edge.years_exp}
But this last query only outputs the final department top 2 results. Not all of the top 2 in each department.
My questions are: (1) why doesn't the second shorter query give all results? and (2) I'm quite new to Arango and ArangoQL, what other things can I do to make sure this is efficient?