Mongodb 从包含约120万条记录的集合中进行Mongo查找查询失败
共有两个集合:警报和警报类型。 警报集合有一个名为:alertTypeId的字段,它是警报类型集合的查找/外键 我需要优化下面的查询,通过加入相应的集合,从Alerts集合中获取数据以及AlertType名称 我使用了聚合函数,如下所示:Mongodb 从包含约120万条记录的集合中进行Mongo查找查询失败,mongodb,aggregation-framework,lookup,Mongodb,Aggregation Framework,Lookup,共有两个集合:警报和警报类型。 警报集合有一个名为:alertTypeId的字段,它是警报类型集合的查找/外键 我需要优化下面的查询,通过加入相应的集合,从Alerts集合中获取数据以及AlertType名称 我使用了聚合函数,如下所示: db.Alerts.aggregate([{ "$match": { "status": { "$ne": -1 },
db.Alerts.aggregate([{
"$match": {
"status": {
"$ne": -1
},
"type": 4
}
}, {
"$lookup": {
"localField": "alertTypeId",
"from": "AlertTypes",
"foreignField": "_id",
"as": "alertTypeRel"
}
}, {
"$project": {
"title": 1,
"type": 1,
"alertTypeId": 1,
"alertTypeRel.alertTypeName": 1,
"priority": 1,
"message": 1,
"status": 1,
"startDate": 1,
"createdAt": 1,
"createdBy": 1,
"validUntil": 1,
"errorFlag": 1,
"extApiId": 1,
"errorMessage": 1,
"autoPublish": 1,
"statusChangedBy": 1
}
},{
"$sort": {
"status": 1,
"createdAt": -1
}
}, {
"$group": {
"_id": null,
"count": {
"$sum": 1
},
"results": {
"$push": "$$ROOT"
}
}
}, {
"$project": {
"total": "$count",
"_id": 0,
"results": {
"$slice": ["$results", 0, 10]
}
}
}], {
"collation": {
"locale": "en",
"strength": 2
},
"allowDiskUse": true,
"cursor": {}
}).pretty();
我也为这些字段编制了索引。对于环境商品:
{
"v" : 2,
"key" : {
"status" : 1,
"createdAt" : -1
},
"name" : "status_1_createdAt_-1"
}
警报和警报类型集合中分别有1250543和117条记录。我也尝试了facet
查询,但也得到了相同的结果:
uncaught exception: Error: command failed: {
"ok" : 0,
"errmsg" : "$push used too much memory and cannot spill to disk. Memory limit: 104857600 bytes",
"code" : 146,
"codeName" : "ExceededMemoryLimit"
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:18:14
_assertCommandWorked@src/mongo/shell/assert.js:639:17
assert.commandWorked@src/mongo/shell/assert.js:729:16
DB.prototype._runAggregate@src/mongo/shell/db.js:266:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1058:12
@(shell):1:1
谢谢推送
$$ROOT
对象时,$group
阶段占用了太多内存,几乎没有修复方法,只需使用$facet
而不是$group
和$project
阶段
- 对于分页,您可以使用
和$skip
阶段$limit
- 要计算文档总数,请使用
运算符$count
来分离$facet
和结果
计数
- 在
阶段之后使用$limit
,因为我们正在获取10个文档,并且只需要查找10个文档$lookup
- 如果需要,在查找后使用
$project
db.Alerts.aggregate([
{
"$match": {
"status": { "$ne": -1 },
"type": 4
}
},
{
"$sort": {
"status": 1,
"createdAt": -1
}
},
{
$facet: {
result: [
{ $skip: 0 },
{ $limit: 10 },
{
"$lookup": {
"localField": "alertTypeId",
"from": "AlertTypes",
"foreignField": "_id",
"as": "alertTypeRel"
}
},
{
"$project": {
"title": 1,
"type": 1,
"alertTypeId": 1,
"alertTypeRel.alertTypeName": 1,
"priority": 1,
"message": 1,
"status": 1,
"startDate": 1,
"createdAt": 1,
"createdBy": 1,
"validUntil": 1,
"errorFlag": 1,
"extApiId": 1,
"errorMessage": 1,
"autoPublish": 1,
"statusChangedBy": 1
}
}
],
count: [{ $count: "total" }]
}
}
],
{
"collation": {
"locale": "en",
"strength": 2
},
"allowDiskUse": true,
"cursor": {}
})
.pretty();
- 为了获得更高的性能,您可以在匹配条件字段和排序字段上使用索引,根据您的查询,您可以在
、状态
和类型
上使用复合索引,查看有关创建数据
“lak”一词在印度以外并不为人所知。谢谢你的回答。但上述查询耗时5分钟以上。此外,我们无法在查找之前对数据进行排序,因为有时,排序将基于查找集合中的警报类型名称,该名称取决于API中的排序请求参数。您是否可以使用
添加此查询的解释状态。explain('executionStats')
请参阅下面链接中添加的解释统计。请看一看,我不确定,我想你必须问到mongodb论坛,我在之前的评论中提到过。我已经问过了。