在 Arango 中查找每组的前 N 个条目
Finding top N entries per group in Arango
我正试图在 Arango (AQL) 中按组高效地找到排名靠前的条目。我有一个相当标准的对象集合和一个边缘集合,代表该部门的部门和员工。
Example purpose: Find the top 2 employees in each department by most years of experience.
示例数据:
“部门”是一个对象集合。以下是一些条目:
_id
name
departments/1
engineering
departments/2
sales
"dept_emp_edges" 是一个通过 id 连接部门和员工对象的边缘集合。
_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
我想根据最多年的经验得出每个部门的前 2 名员工:
department
employee
years_exp
departments/1
employee/3
5
departments/1
employee/2
4
departments/2
employee/1
6
长时间的查询
以下查询有效!但是在大桌子上有点慢,感觉效率低下。
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}
我不喜欢这个,因为这里有 3 个循环,感觉效率很低。
简短查询
然而,我试着写:
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}
但是这最后一个查询只输出最终的部门前 2 个结果。不是每个部门的前2名。
我的问题是:(1) 为什么第二个较短的查询没有给出所有结果? (2) 我对 Arango 和 ArangoQL 还很陌生,我还能做些什么来确保这是有效的?
您的第一个查询不正确 (Query: AQL: collection or view not found: dep_emp_edge (while parsing)
) - 因为我只能猜测您的意思,所以我暂时忽略它。
您的较小查询将总体结果限制为两个 - 直观上相反 - 因为您没有按部门分组。
我建议采用一种稍微不同的方法:使用边缘集合作为中心源并按 _from 分组,每个部门返回一个文档,包含两个最高结果员工(如果存在)的数组,而不是每个员工一个文档:
FOR edge IN dept_emp_edges
SORT edge.years_exp DESC
COLLECT dep = edge._from INTO deps
LET emps = (
FOR e in deps
LIMIT 2
RETURN ZIP(["employee", "years_exp"], [e.edge._to, e.edge.years_exp])
)
RETURN {"department": dep, employees: emps}
对于您的示例数据库,此 returns:
[
{
"department": "departments/1",
"employees": [
{
"employee": "employees/3",
"years_exp": 5
},
{
"employee": "employees/2",
"years_exp": 4
}
]
},
{
"department": "departments/2",
"employees": [
{
"employee": "employees/1",
"years_exp": 6
}
]
}
]
如果查询速度太慢,dept_emp_edges
集合的 year_exp
字段上的索引可能会有所帮助(Explain 建议这样做)。
我正试图在 Arango (AQL) 中按组高效地找到排名靠前的条目。我有一个相当标准的对象集合和一个边缘集合,代表该部门的部门和员工。
Example purpose: Find the top 2 employees in each department by most years of experience.
示例数据:
“部门”是一个对象集合。以下是一些条目:
_id | name |
---|---|
departments/1 | engineering |
departments/2 | sales |
"dept_emp_edges" 是一个通过 id 连接部门和员工对象的边缘集合。
_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 |
我想根据最多年的经验得出每个部门的前 2 名员工:
department | employee | years_exp |
---|---|---|
departments/1 | employee/3 | 5 |
departments/1 | employee/2 | 4 |
departments/2 | employee/1 | 6 |
长时间的查询
以下查询有效!但是在大桌子上有点慢,感觉效率低下。
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}
我不喜欢这个,因为这里有 3 个循环,感觉效率很低。
简短查询
然而,我试着写:
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}
但是这最后一个查询只输出最终的部门前 2 个结果。不是每个部门的前2名。
我的问题是:(1) 为什么第二个较短的查询没有给出所有结果? (2) 我对 Arango 和 ArangoQL 还很陌生,我还能做些什么来确保这是有效的?
您的第一个查询不正确 (Query: AQL: collection or view not found: dep_emp_edge (while parsing)
) - 因为我只能猜测您的意思,所以我暂时忽略它。
您的较小查询将总体结果限制为两个 - 直观上相反 - 因为您没有按部门分组。
我建议采用一种稍微不同的方法:使用边缘集合作为中心源并按 _from 分组,每个部门返回一个文档,包含两个最高结果员工(如果存在)的数组,而不是每个员工一个文档:
FOR edge IN dept_emp_edges
SORT edge.years_exp DESC
COLLECT dep = edge._from INTO deps
LET emps = (
FOR e in deps
LIMIT 2
RETURN ZIP(["employee", "years_exp"], [e.edge._to, e.edge.years_exp])
)
RETURN {"department": dep, employees: emps}
对于您的示例数据库,此 returns:
[
{
"department": "departments/1",
"employees": [
{
"employee": "employees/3",
"years_exp": 5
},
{
"employee": "employees/2",
"years_exp": 4
}
]
},
{
"department": "departments/2",
"employees": [
{
"employee": "employees/1",
"years_exp": 6
}
]
}
]
如果查询速度太慢,dept_emp_edges
集合的 year_exp
字段上的索引可能会有所帮助(Explain 建议这样做)。