满足条件时才填充

我有一个mongodb数据库,并且使用了与nodejs一起的mongoose。

只有当我有字段“temtussvinculado = true”时,我需要从填充“tabela_tuss”的下一个查询返回数据。

这是我在做什么:

ConvProced.find({'convenioId':new ObjectId(req.params.id)}) .populate('convenioId') .populate({ path:'procedId', populate:{ path:'tabela_tuss', match: { 'procedId.temtussvinculado': true} } }) .exec( (err,data) => { callback(err,data,res) }) 

我的问题是,我与“程序.temtussvinculado:真”的匹配没有效果,“tabela_tuss”从来没有填充。

我究竟做错了什么?

这是我的模式:

 //// var conveniosSchema = new mongoose.Schema({ nome: {type: String, unique:true}, ativo: {type: Boolean} }); module.exports = mongoose.model('Convenio', conveniosSchema,'convenios' ); //// //// const agProcedimentosSchema = new mongoose.Schema({ ativo:{type:Boolean}, temtussvinculado:{type:Boolean}, tabela_tuss:{type:mongoose.Schema.Types.ObjectId, ref:'Tuss_22'} }); module.exports = mongoose.model('Ag_procedimento', agProcedimentosSchema,'ag_procedimentos' ); /// //// const tuss_22Schema = new mongoose.Schema({ codigo: {type: String, unique:true}, descricao:{type: String}, tabela:{type: String} }); module.exports = mongoose.model('Tuss_22', tuss_22Schema,'tuss_22' ); //// //../models/convenioprocedimento var conveniosProcedsSchema = new mongoose.Schema({ convenioId:{type:mongoose.Schema.Types.ObjectId, ref:'Convenio'}, procedId:{type:mongoose.Schema.Types.ObjectId, ref:'Ag_procedimento'}, valor_particular:{type:Number}, valor_convenio:{type:Number}, }); module.exports = mongoose.model('ConvenioProcedimento', conveniosProcedsSchema,'conveniosprocedimentos' ); //my query: const ConvProced = require('../models/convenioprocedimento'); ConvProced.find({'convenioId':new ObjectId(req.params.id)}) .populate('convenioId') .populate({ path:'procedId', populate:{ path:'tabela_tuss', match: { 'procedId.temtussvinculado': true} } }) .exec( (err,data) => { callback(err,data,res) }) 

你实际上在这里要问的是“只填充数据中的条件说明这么做的地方” ,这实际上并不是“ .populate() ”的“直接”支持的操作,或者是“嵌套填充”语法的使用。

所以,如果你想强制实际填充项目的“条件”,那么你必须手动处理填充调用。

你的情况的基本前提是,你需要检查你需要从“初始”顶级.populate()调用得到的值,但是当给定的条件实际允许时,“仅”调用“内部”它。

所以你的代码可能看起来像这样使用Promise.all()基本上“循环”或.map()每个查询结果的“Promises”,并testingproceedid.temtussvinculado ,看看它是true/false ,在哪里true我们实际上发出一个Model.populate()调用,否则只是返回当前状态的数据:

 ConvProced.find({'convenioId':new ObjectId(req.params.id)}) .populate('convenioId procedId') .exec() .then(data => Promise.all( data.map( d => ( d.proceedid.temtussvinculado ) ? mongoose.model('Tuss_22').populate(d,{ path: 'proceedId.tabela_tuss' }) : d ) ) ) ) // Populated conditionally .then( data => // Do something with data ) .catch(err => console.error(err)); // or something else with error 

除“承诺”之外,还有其他不同的选项可用,但它是不依赖的选项。 像async.map这样的其他情况可以做同样的事情,但是如果你还没有这个附加的依赖项,

 ConvProced.find({'convenioId':new ObjectId(req.params.id)}) .populate('convenioId procedId') .exec((err,data) => { if (err) throw err; async.map(data,(d,callback) => ( d.proceedid.temtussvinculado ) ? mongoose.model('Tuss_22').populate(d,{ path: 'proceedId.tabela_tuss' },callback) : callback(null,d) (err,data) => { if (err) throw err; // or something // Conditionally populated } ) }) 

还用一个完整的工作示例进行了演示,实际上它比您需要做的更复杂一点,因为在此示例中,“condition”嵌套在另一个数组中:

 const async = require('async'), mongoose = require('mongoose'), Schema = mongoose.Schema; mongoose.Promise = global.Promise; mongoose.set('debug',true); mongoose.connect('mongodb://localhost/test'); const subInnerSchema = new Schema({ label: String }); const innerSchema = new Schema({ name: String, populate: Boolean, subs: [{ type: Schema.Types.ObjectId, ref: 'Sub' }] }); const outerSchema = new Schema({ title: String, inners: [{ type: Schema.Types.ObjectId, ref: 'Inner' }] }); const Sub = mongoose.model('Sub', subInnerSchema); const Inner = mongoose.model('Inner', innerSchema); const Outer = mongoose.model('Outer', outerSchema); function log(data) { console.log(JSON.stringify(data, undefined, 2)) } async.series( [ // Clean data (callback) => async.each(mongoose.models,(model,callback) => model.remove({},callback),callback), // Insert some data (callback) => async.waterfall( [ (callback) => Sub.create([1,2,3,4].map( label => ({ label })),callback), (subs,callback) => Inner.create( [0,2].map(x => subs.slice(x,x+2)) .map((el,i) => ({ name: i+i, populate: i == 1, subs: el })), callback ), (inners,callback) => Outer.create( inners.map((inner,i) => ({ title: i+1, inners: [inner] })), callback ), ], callback ), // Conditional populate async.map version (callback) => Outer.find().populate('inners').exec((err,outers) => { if (err) callback(err); async.map( outers, (outer,callback) => async.map( outer.inners, (inner,callback) => (inner.populate) ? Inner.populate(inner,{ path: 'subs' },callback) : callback(null,inner), (err,inners) => { if (err) callback(err); outer.inners = inners callback(null,outer); } ), (err,outers) => { if (err) callback(err); log(outers); callback(); } ); }), // Conditional populate Promise (callback) => Outer.find().populate('inners').exec() .then(outers => Promise.all( outers.map( outer => new Promise((resolve,reject) => { Promise.all( outer.inners.map( inner => (inner.populate) ? Inner.populate(inner,{ path: 'subs' }) : inner ) ).then(inners => { outer.inners = inners; resolve(outer) }) .catch(reject) }) ) ) ) .then(outers => { log(outers); callback(); }) .catch(err => callback(err)) ], (err) => { if (err) throw err; mongoose.disconnect(); } ); 

其中产生显示“条件”select的输出,当然使用任何一种方法:

 Mongoose: subs.remove({}, {}) Mongoose: inners.remove({}, {}) Mongoose: outers.remove({}, {}) Mongoose: subs.insert({ label: '1', _id: ObjectId("5961830256bf9e2d0fcf13b3"), __v: 0 }) Mongoose: subs.insert({ label: '2', _id: ObjectId("5961830256bf9e2d0fcf13b4"), __v: 0 }) Mongoose: subs.insert({ label: '3', _id: ObjectId("5961830256bf9e2d0fcf13b5"), __v: 0 }) Mongoose: subs.insert({ label: '4', _id: ObjectId("5961830256bf9e2d0fcf13b6"), __v: 0 }) Mongoose: inners.insert({ name: '0', populate: false, _id: ObjectId("5961830256bf9e2d0fcf13b7"), subs: [ ObjectId("5961830256bf9e2d0fcf13b3"), ObjectId("5961830256bf9e2d0fcf13b4") ], __v: 0 }) Mongoose: inners.insert({ name: '2', populate: true, _id: ObjectId("5961830256bf9e2d0fcf13b8"), subs: [ ObjectId("5961830256bf9e2d0fcf13b5"), ObjectId("5961830256bf9e2d0fcf13b6") ], __v: 0 }) Mongoose: outers.insert({ title: '1', _id: ObjectId("5961830256bf9e2d0fcf13b9"), inners: [ ObjectId("5961830256bf9e2d0fcf13b7") ], __v: 0 }) Mongoose: outers.insert({ title: '2', _id: ObjectId("5961830256bf9e2d0fcf13ba"), inners: [ ObjectId("5961830256bf9e2d0fcf13b8") ], __v: 0 }) Mongoose: outers.find({}, { fields: {} }) Mongoose: inners.find({ _id: { '$in': [ ObjectId("5961830256bf9e2d0fcf13b7"), ObjectId("5961830256bf9e2d0fcf13b8") ] } }, { fields: {} }) Mongoose: subs.find({ _id: { '$in': [ ObjectId("5961830256bf9e2d0fcf13b5"), ObjectId("5961830256bf9e2d0fcf13b6") ] } }, { fields: {} }) [ { "_id": "5961830256bf9e2d0fcf13b9", "title": "1", "__v": 0, "inners": [ { "_id": "5961830256bf9e2d0fcf13b7", "name": "0", "populate": false, "__v": 0, "subs": [ "5961830256bf9e2d0fcf13b3", "5961830256bf9e2d0fcf13b4" ] } ] }, { "_id": "5961830256bf9e2d0fcf13ba", "title": "2", "__v": 0, "inners": [ { "_id": "5961830256bf9e2d0fcf13b8", "name": "2", "populate": true, "__v": 0, "subs": [ { "_id": "5961830256bf9e2d0fcf13b5", "label": "3", "__v": 0 }, { "_id": "5961830256bf9e2d0fcf13b6", "label": "4", "__v": 0 } ] } ] } ] Mongoose: outers.find({}, { fields: {} }) Mongoose: inners.find({ _id: { '$in': [ ObjectId("5961830256bf9e2d0fcf13b7"), ObjectId("5961830256bf9e2d0fcf13b8") ] } }, { fields: {} }) Mongoose: subs.find({ _id: { '$in': [ ObjectId("5961830256bf9e2d0fcf13b5"), ObjectId("5961830256bf9e2d0fcf13b6") ] } }, { fields: {} }) [ { "_id": "5961830256bf9e2d0fcf13b9", "title": "1", "__v": 0, "inners": [ { "_id": "5961830256bf9e2d0fcf13b7", "name": "0", "populate": false, "__v": 0, "subs": [ "5961830256bf9e2d0fcf13b3", "5961830256bf9e2d0fcf13b4" ] } ] }, { "_id": "5961830256bf9e2d0fcf13ba", "title": "2", "__v": 0, "inners": [ { "_id": "5961830256bf9e2d0fcf13b8", "name": "2", "populate": true, "__v": 0, "subs": [ { "_id": "5961830256bf9e2d0fcf13b5", "label": "3", "__v": 0 }, { "_id": "5961830256bf9e2d0fcf13b6", "label": "4", "__v": 0 } ] } ] } ] 

所以你可以看到那里有一个“布尔”字段,它正在被testing以确定是否执行.populate()或者只是返回普通数据。