2016-03-24 22 views
7

Voglio mostrare i prodotti per ID (56e641d4864e5b780bb992c6 e 56e65504a323ee0812e511f2) e mostrare il prezzo dopo averlo sottratto dallo sconto se disponibile.

posso contare il prezzo finale utilizzando aggregata, ma questo ritorno tutti i documenti in una collezione, come farlo tornare solo le partite ids

"_id" : ObjectId("56e641d4864e5b780bb992c6"), 
"title" : "Keyboard", 
"discount" : NumberInt(10), 
"price" : NumberInt(1000) 

"_id" : ObjectId("56e65504a323ee0812e511f2"), 
"title" : "Mouse", 
"discount" : NumberInt(0), 
"price" : NumberInt(1000) 

"_id" : ObjectId("56d90714a48d2eb40cc601a5"), 
"title" : "Speaker", 
"discount" : NumberInt(10), 
"price" : NumberInt(1000) 

questa è la mia domanda

productModel.aggregate([ 
     { 
      $project: { 
       title : 1, 
       price: { 
        $cond: { 
         if: {$gt: ["$discount", 0]}, then: {$subtract: ["$price", {$divide: [{$multiply: ["$price", "$discount"]}, 100]}]}, else: "$price" 
        } 

       } 
      } 
     } 
    ], function(err, docs){ 
     if (err){ 
      console.log(err) 
     }else{ 
      console.log(docs) 
     } 
    }) 

e se aggiungo questo $in query, restituisce array vuoto

productModel.aggregate([ 
      { 
       $match: {_id: {$in: ids}} 
      }, 
      { 
       $project: { 
        title : 1, 
        price: { 
         $cond: { 
          if: {$gt: ["$discount", 0]}, then: {$subtract: ["$price", {$divide: [{$multiply: ["$price", "$discount"]}, 100]}]}, else: "$price" 
        } 

       } 
      } 
     } 
    ], function(err, docs){ 
     if (err){ 
      console.log(err) 
     }else{ 
      console.log(docs) 
     } 
    }) 

risposta

11

La variabile ids sarà composta da "stringhe" e non da valori ObjectId.

Manomettere i valori stringa "autocasts" per ObjectId nel tipo corretto nelle query regolari, ma questo does not happen in the aggregation pipeline, come descritto nel numero 1399.

Invece si deve fare il casting corretta digitare manualmente:

ids = ids.map(function(el) { return mongoose.Types.ObjectId(el) }) 

Poi si possono usare nel vostro stadio di cantiere:

{ "$match": { "_id": { "$in": ids } } } 

La ragione è che le tubazioni di aggregazione "tipicamente" toglie struttura del documento, e quindi mangusta non fa presumere che lo "schema" si applica al documento in una data fase della pipeline.

È discutibile che il "primo" stadio della pipeline quando è uno stadio $match dovrebbe fare questo, poiché in effetti il ​​documento non è alterato. Ma in questo momento non è così che succede.

Eventuali valori che possono essere "stringhe" o almeno non il tipo BSON corretto devono essere espressi manualmente per corrispondere.

+0

Ecco, ora funziona. ma di solito lancio l'id come stringa in findOneAndUpdate o in un'altra query, e funziona bene, il problema si verifica solo in forma aggregata? –

+1

@MuhammadFasalirRahman Questo è esattamente ciò a cui ho risposto. Un '.find()' può usare lo 'Schema' che ovviamente ha un tipo predefinito di' ObjectId' per il campo '_id'. Le condutture di aggregazione non ** usano ** lo schema, come ho già spiegato. –

+0

Questo non funziona in mangusta 5 –