我有一个类似树的架构,它指定了一组父母和一组孩子。
子集合可能包含数百万个文档 - 每个文档都包含少量数据,并且对它所属的父项的引用存储为字符串(可能是我的第一个错误)。
父母的收集要小得多,但可能仍然数万,并会随着时间的推移慢慢增长。一般来说,单亲家长可能只有10个孩子,或多达50,000个孩子(可能更多,但有些不太可能)。
单个子文档可能如下所示:
{
_id: ObjectId("507f191e810c19729de860ea"),
info: "Here's some info",
timestamp: 1234567890.0,
colour: "Orange",
sequence: 1000,
parent: "12a4567b909c7654d212e45f"
}
其对应的父记录(位于单独的集合中)可能如下所示:
{
_id: ObjectId("12a4567b909c7654d212e45f")
info: "Blah",
timestamp: 1234567890.0
}
我在mongoose中的查询(包含请求中的父ID)如下所示:
/* GET all children with the specified parent ID */
module.exports.childrenFromParent = function(req, res) {
parentID = req.params.parentID;
childModel.find({
"parentid": parentID
}).sort({"sequence": "asc"}).exec(
function(err, children) {
if (!children) {
sendJSONResponse(res, 404, {
"message": "no children found"
});
return;
} else if (err) {
sendJSONResponse(res, 404, err);
return;
}
sendJSONResponse(res, 200, children);
}
);
};
所以基本上发生的事情是,查询必须在整个子集合中搜索具有与提供的ID匹配的父文档的任何文档。
我目前将这个父ID保存为子集合模式中的字符串(上面代码中的childModel),这可能是一个坏主意,但是,我的API提供了父ID作为字符串。请求。
如果有人对如何修复我的架构或更改查询以提高性能有任何想法,我们将不胜感激!
答案 0 :(得分:1)
从评论中写下:
您可以通过在parent
字段上添加索引来帮助加快和优化查询。您可以通过执行以下操作添加(升序)索引:
db.collection.createIndex( { parent: 1 } )
您可以通过向查询添加.explain("executionStats")
来分析索引的好处。有关详细信息,请参阅docs。
在大型集合上添加索引可能需要一些时间,您可以通过运行以下查询来检查状态:
db.currentOp(
{
$or: [
{ op: "query", "query.createIndexes": { $exists: true } },
{ op: "insert", ns: /\.system\.indexes\b/ }
]
}
)
修改:如果您按sequence
排序,则可能需要为parent
和sequence
添加compound index。
答案 1 :(得分:1)
你为什么不在你的执行官之前使用.lean()?您真的希望所有文档都是Mongoose文档或只是简单的JSON文档吗?使用lean(),您将无法获得Mongoose文档附带的所有额外的getter和setter。这可以轻松地从响应时间中减少一两秒钟。