如何在Mongoose中实现部分文档嵌入?

时间:2017-04-01 16:14:08

标签: node.js mongodb mongoose mongoose-populate

当主题属于某个类别时,我在主题和类别之间有一个简单的关系。

因此架构如下所示:

const CategorySchema = new mongoose.Schema({
 name:  String,
 slug: String,
 description: String
});

主题

const TopicSchema = new mongoose.Schema({
  category: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Category'
  },
  title: String,
  slug: String,
  body:  String,
  created: {type: Date, default: Date.now}
});

我想在主题

中实现特定的类别嵌入
{
    category: {
        _id: ObjectId('abc'),
        slug: 'catslug'
    },
    title: "Title",
    slug: "topictitle",
    ...
}

它将帮助我避免不必要的人口并获得绩效奖金。 我不想嵌入整个文档,因为我想有时更改类别(这是一种罕见的操作)并维护引用。

1 个答案:

答案 0 :(得分:0)

希望这有帮助,在我自己的项目中完成它,以便在常见用例中保存一些RTT。确保您在更新时正在处理这两份副本。

parent.model.js:

const mongoose = require('mongoose');

const childEmbeddedSchema = new mongoose.Schema({
    _id: {type: mongoose.Schema.Types.ObjectId, ref: 'Child', auto: false, required: true, index: true},
    someFieldIWantEmbedded: {type: String}
});

const parentSchema = new mongoose.Schema({
    child: { type: childEmbeddedSchema },
    moreChildren: { type: [{type: childEmbeddedSchema }] }
});

module.exports = mongoose.model('Parent', parentSchema);

child.model.js:

const mongoose = require('mongoose');

const childSchema = new mongoose.Schema({
    someFieldIWantEmbedded: {type: String},
    someFieldIDontWantEmbedded: {type: Number},
    anotherFieldIDontWantEmbedded: {type: Date}
});

module.exports = mongoose.model('Child', childSchema);

parent.controller.js:

const mongoose = require('mongoose');
const Parent = require('path/to/parent.model');

exports.getAll = (req, res, next) => {
    const query = Parent.find();

    // only populate if requested! if true, will replace entire sub-document with fetched one.
    if (req.headers.populate === 'true') {
        query.populate({
            path: 'child._id',
            select: `someFieldIWantEmbedded ${req.headers.select}`
        });
        query.populate({
            path: 'moreChildren._id',
            select: `someFieldIWantEmbedded ${req.headers.select}`
        });
    }

    query.exec((err, results) => {
        if (err) {
            next(err);
        } else {
            res.status(200).json(results);
        }
    });
};