似乎选项 A 是最好的,至少在我测试的情况下。
我做了如下性能测试:
我创建了一个包含 3.000.000 个文档的集合,其中包含 2 个字段:
-
created_at:2018-01-01T00:00:00.000Z 和 2030-01-01T00:00:00.000Z 之间的随机日期
-
color:随机字符串,31 种不同的选项
我做了一个查询,以获取 17 种不同颜色中每种颜色的最新创建文档。
结果
|
No index |
{ color: 1, created_at: -1 } |
{ created_at: -1, color: 1 } |
| A1) One FindOne (shell) |
70 ms |
60 ms |
60 ms |
| A2) FindOnes in parallel (JS) |
21944 ms |
543 ms |
572 ms |
| B) Aggregate - Group - First |
QueryExceededMemoryLimitNoDiskUseAllowed |
9120 ms |
10200 ms |
| C) Aggregate - Facet |
QueryExceededMemoryLimitNoDiskUseAllowed |
3860 ms |
4770 ms |
选项 A1 是最快的,但这仅适用于一种颜色(我无法通过 shell 并行执行)。所以真正的赢家是选项A2!另请注意,A2 是通过连接到外部数据库的本地运行的 JS 脚本完成的。它仍然比直接通过 shell 完成的其他选项快得多。
我检查了并行执行 5 个 findOne 而不是 17 个的影响:
A3) 并行查找 (JS) | 6656 毫秒 | 334 毫秒 | 339 毫秒
这明显更快。我怀疑如果您需要超过 17 个案例,其他选择可能会更好。它与我的需求无关,所以我没有对此进行测试。
为了完整起见,确切的查询:
A1)
db.getCollection('colors').findOne({ color: 'Ivory' }, { sort: { created_at: -1 } })
A2)
const latest = await Promise.all(colors.map((c) => mongodb.collection('colors').findOne({ color: c }, { sort: { created_at: -1 } })));
B)
db.getCollection('colors').aggregate([
{ $match: { color: { $in: [
'Ivory',
'Teal',
'Silver',
'Purple',
'Navy blue',
'Pea green',
'Gray',
'Orange',
'Maroon',
'Charcoal',
'Aquamarine',
'Coral',
'Fuchsia',
'Wheat',
'Lime',
'Crimson',
'Khaki'
] } } },
{ $sort: { created_at: -1 } },
{
$group: {
_id: "$color",
latest: { $first: "$$ROOT" }
}
},
]);
C)
db.getCollection('colors').aggregate([
{ $match: { color: { $in: [
'Ivory',
'Teal',
'Silver',
'Purple',
'Navy blue',
'Pea green',
'Gray',
'Orange',
'Maroon',
'Charcoal',
'Aquamarine',
'Coral',
'Fuchsia',
'Wheat',
'Lime',
'Crimson',
'Khaki'
] } } },
{ $sort: { created_at: -1 } },
{
$facet: {
Ivory: [
{ $match: { color: 'Ivory' } },
{ $limit: 1 },
],
Teal: [
{ $match: { color: 'Teal' } },
{ $limit: 1 },
],
Silver: [
{ $match: { color: 'Silver' } },
{ $limit: 1 },
],
Purple: [
{ $match: { color: 'Purple' } },
{ $limit: 1 },
],
Navyblue: [
{ $match: { color: 'Navy blue' } },
{ $limit: 1 },
],
Peagreen: [
{ $match: { color: 'Pea green' } },
{ $limit: 1 },
],
Gray: [
{ $match: { color: 'Gray' } },
{ $limit: 1 },
],
Orange: [
{ $match: { color: 'Orange' } },
{ $limit: 1 },
],
Maroon: [
{ $match: { color: 'Maroon' } },
{ $limit: 1 },
],
Charcoal: [
{ $match: { color: 'Charcoal' } },
{ $limit: 1 },
],
Aquamarine: [
{ $match: { color: 'Aquamarine' } },
{ $limit: 1 },
],
Coral: [
{ $match: { color: 'Coral' } },
{ $limit: 1 },
],
Fuchsia: [
{ $match: { color: 'Fuchsia' } },
{ $limit: 1 },
],
Wheat: [
{ $match: { color: 'Wheat' } },
{ $limit: 1 },
],
Lime: [
{ $match: { color: 'Lime' } },
{ $limit: 1 },
],
Crimson: [
{ $match: { color: 'Crimson' } },
{ $limit: 1 },
],
Khaki: [
{ $match: { color: 'Khaki' } },
{ $limit: 1 },
],
}
},
]);