我有一組用戶(約 8k 檔案)和一組作業(約 150k 檔案)。我需要使用一個階段創建一個聚合,該階段可以找到每個用戶被接受的作業(在作業模型中接受的是一個 ObjectIds 陣列):
db.getCollection('users')
.aggregate([
{
$lookup: {
from: 'jobs',
as: 'jobs',
let: { accepted: '$_id' },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $gte: ['$timestamp', 1643223600] },
{ $in: ['$$accepted', '$accepted'] }
]
}
},
},
]
}
},
])
這種聚合非常緩慢。即使將輸出記錄的數量限制為 10 也需要大約 1 分鐘才能完成。雖然,時間戳大于 1643223600 的作業數量并不多——大約是 3000 個檔案。我添加了以下索引:
{timestamp: -1},
{accepted: 1}
但這無濟于事。但是,如果我創建資料庫的副本并洗掉所有不滿足時間戳條件的班次,則聚合作業得更快(幾秒鐘)。這是否意味著索引由于某種原因不起作用?如果在作業集合上運行一個簡單的查詢,并在接受欄位上加上一個條件的解釋,則表明執行了 IXSCAN
UPD:由于 $in 不適用于復合索引,因此 Mongodb4.4 的解決方法是:
{
$lookup: {
from: 'jobs',
as: 'jobs',
localField: '_id',
foreignField: 'accepted'
}
},
{ $match: { $expr: { $ne: [{ $size: '$jobs' }, 0] } } },
{ $unwind: '$jobs' },
{
$match: { 'jobs.timestamp': { $gte: 1643223600 } }
},
uj5u.com熱心網友回復:
查詢
(需要 MongoDB 5)
users.aggregate(
[{"$lookup":
{"from":"jobs",
"localField":"_id",
"foreignField":"accepted",
"pipeline":[{"$match":{"timestamp":{"$gte":1643223600}}}],
"as":"jobs"}}])
在 上創建多鍵索引后嘗試此操作accepted,如果需要timestamp也可以。
即使在 Mongodb 5 中,聚合$in也無法使用索引,因此未使用。
請參閱此處關于$expr和索引使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/422852.html
標籤:
