mongodb聚合,基于查找结果排序
假设我有以下数据架构(我只报告几个字段) 托收单mongodb聚合,基于查找结果排序,mongodb,sorting,aggregation-framework,Mongodb,Sorting,Aggregation Framework,假设我有以下数据架构(我只报告几个字段) 托收单 | id | service | customer | |-------|---------|----------| | O001 | SRV001 | CST001 | | O002 | SRV001 | CST001 | | O003 | SRV001 | CST002 | | O004 | SRV002 | CST003 | | O005 | SRV002 | CST002 | | O006
| id | service | customer |
|-------|---------|----------|
| O001 | SRV001 | CST001 |
| O002 | SRV001 | CST001 |
| O003 | SRV001 | CST002 |
| O004 | SRV002 | CST003 |
| O005 | SRV002 | CST002 |
| O006 | SRV003 | CST004 |
收款客户
| id | name | city |
|--------|---------|----------|
| CST001 | Paul | New York |
| CST002 | Anna | London |
| CST003 | John | Milan |
| CST004 | Julia | Paris |
假设我想根据客户的姓名对订单进行排序
其想法是使用一个带有$lookup的聚合,将客户加入到订单中,并对结果进行排序
db.order.aggregate([
{ $lookup: { 'foreignField': 'id',
'as': '__customer',
'from': 'customer',
'localField':'customer'} },
{ $unwind: '$__customer'},
{ $sort: { '__customer.name': 1 } }
])
如果您的数据有限,这项功能可以正常工作。如果您有大量数据,它将不起作用,因为排序是在$lookup结果上执行的,因此mongodb没有要使用的索引,即使customer集合中的字段“name”有索引
我认为没有办法做到这一点
有人能证实吗?说:
$match和$sort管道操作符可以在管道的开头使用索引
还有更多:
在版本3.2中更改:从MongoDB 3.2开始,索引可以覆盖聚合管道。在MongoDB 2.6和3.0中,索引不能覆盖聚合管道,因为即使管道使用索引,聚合仍然需要访问实际文档
据此,MongoDB(3.2及更高版本)聚合使用索引
不过,您的管道有一些技巧。例如,您可以聚合客户
表,而不是订单
。对其排序,然后对订单执行查找
或者您可以通过客户对进行分组,然后执行查找。我不认为它会更快(实际上我认为它会更慢),但你可以试着想想
不要忘记使用匹配
和限制
——它们加快了聚合速度。即使在大型管道中,您通常也可以在更接近开始的地方进行匹配,但有时您需要好好考虑。聚合客户表不是一个选项,因为关系不是1到1。我需要一个通用解决方案一些过滤器(使用匹配实现)可能存在,但最坏的情况是它不存在。@lorenzo您不需要1对1关系<代码>查找
对于一个字段id
使用展开
会给你一对一的关系,但是当你按照客户进行排序
时,名称
你会得到多个订单给一个客户
关系,这与排序客户
和查找订单
(对于订单
,没有解除
)。您将获得一份客户列表(其中包含订单列表)。这里有一个常见情况-如果您只需要前20份订单,那么您可以限制(20)您的客户,然后解除
订单,按客户排序(因为解除可以自行排序)和限制(20)再说一遍。@Lorenzo只是为了确保我们谈论同样的事情,这是我建议的管道:db.customer.aggregate([{$sort:{'name':1},{$lookup:{'localField':''id','from':'order','as':'orders',},{$match:{$orders:{$gt:[]},{$limit 20},{$unwind:'$orders'},{$limit:20},]
谢谢,下周我会去看看。我这周不在家