假设我具有以下数据架构(我只报告了几个字段)
托收单
| 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也没有索引可使用。
我认为没有办法实现这一目标。
有人可以确认吗?
答案 0 :(得分:0)
$ match和$ sort管道运算符出现在管道的开始处时可以利用索引。
更多:
在3.2版中进行了更改:从MongoDB 3.2开始,索引可以覆盖聚合管道。在MongoDB 2.6和3.0中,索引无法覆盖聚合管道,因为即使管道使用索引,聚合仍需要访问实际文档。
据此,MongoDB(3.2及更高版本)聚合使用索引。
但是,您的管道有一些技巧。例如,您可以聚合customer
表,而不是order
表。对其进行排序,然后为lookup
做orders
。
或者您可以group
之前customer
,然后执行lookup
。我不认为它会运行得更快(实际上我认为它会更慢),但是您可以尝试一下。
请不要忘记使用matches
和limits
-它们可以加快聚合速度。即使在大型管道中,您通常也可以match
更接近开始,但有时您仍然需要考虑清楚。