在Mongoose中填充所有字段?

5

在运行mongoose查询时,是否有一种方法可以填充所有字段,以防您事先不知道哪些字段是引用文档?像这样的东西:

schema = new Schema({ ref: {type:ObjectId, ref:'ref'}});
db = Model('data', schema);

db.find({}).populate('*').
// or
db.find({}).populate({path:'*'}).

//=> {ref: {_id:...,}} // "ref" is populated automatically

1
如果您可以访问模式,使用 mongoose-autopopulate 可以实现此操作。 - Rudra
谢谢,不幸的是,它只在模式中添加autopopulate:true的字段上起作用。但是看着它的代码,我认为我可以创建一个类似的插件,真正自动填充所有字段。 - laggingreflex
2
这似乎是一个非常值得怀疑的事情。人口普查很昂贵,只应在必要时进行。 - JohnnyHK
3个回答

6

我写了一个小插件。它遍历模式并查找具有ref属性的字段,并将它们作为路径添加到.populate()中,在预查找钩子中使用。在Mongoose v4上进行了测试。

function autoPopulateAllFields(schema) {
    var paths = '';
    schema.eachPath(function process(pathname, schemaType) {
        if (pathname=='_id') return;
        if (schemaType.options.ref)
            paths += ' ' + pathname;
    });

    schema.pre('find', handler);
    schema.pre('findOne', handler);

    function handler(next) {
        this.populate(paths);
        next();
    }
};
module.exports = autoPopulateAllFields;

var articleSchema = new Schema({
    text: {type: 'String'},
    author: {type: 'ObjectId', ref: 'user'}
});
articleSchema.plugin(autoPopulateAllFields);
var Article = mongoose.model('article', articleSchema);

Article.find({}) => [ {text:..., author: { _id:..., name:... /*auto-populated*/} } ]

1
为什么不使用方法?总是填充所有的坏习惯。 - Ninja Coding
1
对于我的mongoose版本,我不得不修改像if ((schemaType.options || schemaType.caster.options).ref) ...这样的代码,并且我必须按路径名称调用populate(),然而这是一个可行的解决方案,谢谢。Ninja不是一种“练习”,它是一种选项,我无法相信你在评论中浪费了敲击键的时间,你一定很无聊。 - ekerner
这将包括带有引用数组的路径吗? - Marc J Cabrer
if应该是这样的:!(type?.caster?.options || type.options).ref - Marc J Cabrer

2
我认为最好在某个地方导出一个包含所有填充字段列表的变量,例如:

export const POPULATED_FIELDS = ['filed1','field2']

然后当您想要填充字段时,只需编写
Model.findById('some_id').populate(POPULATED_FIELDS)

0
在我的情况下,对于每个模型,我还有一个类,类中包含一些方法,这些方法返回每个情况所需的相关信息。这使我能够为每个类创建自定义的“过滤”字段列表,用于查询选项: 在GET路由上返回什么,在PUT路由上允许修改什么,以及要填充哪些字段等等。
当需要添加或删除任何“允许”的字段时,只需在类方法中进行操作,而不是在代码的其他部分随处修改。
例如:
// all imports done

class Users {
  // Query parameters
  sortBy() { return 'name'; } 
  getAllFieldsFilter() { return 'name email membertype created_at updated_at'; }
  getAllPopulateIndexed() { return { path: 'membertype', select: 'name canpost' };}
  
  // other methods...
  constructor() {}
}
module.exports = {
  Users,
};

以后可以用于查询,例如:
User.find(queryOptions, Users.getAllFieldsFilter())
  .sort(Users.sortBy())
  .populate(Users.getAllPopulateIndexed());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接