MongoDB 嵌入式文档:大小限制和聚合性能问题

MongoDB embedded documents: size limit and aggregation performance concerns

在MongoDB的文档中,建议将尽可能多的数据放在一个文档中。还建议不要使用基于 ObjectId ref 的子文档,除非这些子文档的数据必须从多个文档中引用。

在我的例子中,我有一个这样的一对多关系:

日志 架构:

const model = (mongoose) => {
    const LogSchema = new mongoose.Schema({
        result: { type: String, required: true },
        operation: { type: Date, required: true },
        x: { type: Number, required: true },
        y: { type: Number, required: true },
        z: { type: Number, required: true }
    });
    const model = mongoose.model("Log", LogSchema);
    return model;
};

机器架构:

const model = (mongoose) => {
    const MachineSchema = new mongoose.Schema({
        model: { type: String, required: true },
        description: { type: String, required: true },
        logs: [ mongoose.model("Log").schema ]
    });
    const model = mongoose.model("Machine", MachineSchema);
    return model;
};
module.exports = model;

每个机器会有很多Production_Log个文件(超过一百万)。使用嵌入式文档,我在测试期间很快就达到了每个文档 16mb 的限制,并且我无法再将 Production_Log 文档添加到 Machine 文档。

我的疑惑

  1. 在这种情况下,是否应该使用子文档作为 ObjectId 引用而不是嵌入文档?

  2. 有没有其他我可以评估的解决方案?

  3. 我将访问 Production_Log 文档以使用聚合框架为每个 Machine 生成统计信息.我应该对模式设计有任何额外的考虑吗?

非常感谢您的建议!

请查看此方法是否适合您的需要

Log 集合将生成更多数据,而 Machine 集合永远不会超过 16MB。不要将 Log 集合嵌入到 Machine 集合中,反之亦然。

您修改后的架构会像这样

机器架构:

const model = (mongoose) => {
    const MachineSchema = new mongoose.Schema({
        model: { type: String, required: true },
        description: { type: String, required: true }        
    });
    const model = mongoose.model("Machine", MachineSchema);
    return model;
};
module.exports = model;

日志架构:

const model = (mongoose) => {
    const LogSchema = new mongoose.Schema({
        result: { type: String, required: true },
        operation: { type: Date, required: true },
        x: { type: Number, required: true },
        y: { type: Number, required: true },
        z: { type: Number, required: true },
        machine: [ mongoose.model("Machine").schema ]
    });
    const model = mongoose.model("Log", LogSchema);
    return model;
};

如果我们仍然超过文档的大小 (16MB),那么在日志模式中,我们可以根据我们生成的日志为每个 Day/Hour/Week 创建一个新文档。

Database normalization不适用于MongoDB

MongoDB 如果将完整信息存储在单个文档中(数据冗余),则扩展性更好。数据库规范化要求将数据拆分到不同的集合中,但是一旦数据增长,就会导致瓶颈问题。

仅使用 LOG 架构:

const model = (mongoose) => {
    const LogSchema = new mongoose.Schema({
        model: { type: String, required: true },
        description: { type: String, required: true },
        result: { type: String, required: true },
        operation: { type: Date, required: true },
        x: { type: Number, required: true },
        y: { type: Number, required: true },
        z: { type: Number, required: true }
    });
    const model = mongoose.model("Log", LogSchema);
    return model;
};

读/写操作以这种方式很好地缩放。

使用 Aggregation 您可以处理数据并计算所需的结果。