2017-07-07 140 views
1

我有一個mongodb數據庫,並且使用帶有nodejs的貓鼬。只有滿足條件時才填充

只有當我有字段「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) 
     }) 

我的問題是,我的比賽與「procedId.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) 
    }) 
+0

''.populate()'的'match'參數實際上是在模擬任何「連接」之前針對集合進行處理的,因爲實際上是如何填充的。所以相反,這應該是'.populate({路徑:'程序Id',匹配:{'temtussvinculado':true},填充:{path:'tabela_tuss'}})' –

+0

謝謝,Neil Lunn先生。它解決了我的問題 –

+0

@Neil Lunn,對不起,我的錯誤。問題仍在繼續。路徑「程序」總是必須填充。如果我遵循你的建議,那麼當temtussvinculado <>是真的時,它就不會被填充。我需要「tabela_tuss」只有在temtussvinculado = true時填充 –

回答

1

什麼你實際上是在問這裏是「僅填充了數據內的條件說這樣做」,這是一件好事實際上不是一個「直接「支持.populate()的行爲或使用」嵌套填充「語法。

所以,如果你想強制實際填充項目的「條件」,那麼你必須手動處理填充調用。

您的情況的基本前提是,您需要檢查您需要從「初始」頂級.populate()調用中獲得的值,但是當給定條件實際上「只」調用「內部」填充時允許它。

所以,你的代碼都可能看起來像這樣用「承諾」使用Promise.all(),你基本上是「循環」或.map()每個查詢結果和測試proceedid.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 

除'Promises'外,還有其他不同的選項,但它是no依賴項選項。備用的情況下,如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 
     } 
    ) 
    }) 

一個完整的工作示例,這實際上是一個小比你更復雜也證明需要做的,因爲「條件」嵌套在該實施例中的另一陣列內:

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(); 
    } 
); 

其中產生從當然使用任一方法表示「有條件的」選擇的輸出,:

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 
      } 
     ] 
     } 
    ] 
    } 
] 

所以你可以看到,在很大程度上有一個「布爾」字段正在測試,以確定是否執行.populate()或只是返回普通數據。

+0

您的解釋非常好。非常感謝你 –

相關問題