2016-03-24 4 views
7

Ich möchte Produkte nach IDs anzeigen (56e641d4864e5b780bb992c6 und 56e65504a323ee0812e511f2) und den Preis nach Abzug durch Rabatt anzeigen, falls verfügbar.

Ich kann den Endpreis zählt Aggregat verwenden, aber diese Rückkehr alle Dokumente in einer Sammlung, wie es nur den Spiele-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) 

das ist meine Abfrage

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

zurückkehren zu machen und wenn ich diese $in Abfrage hinzufügen, gibt es leere Array

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

Antwort

11

Ihre ids Variable wird aus "Strings" und nicht ObjectId Werten aufgebaut.

Mongoose "autocasts" Zeichenfolge Werte für ObjectId in ihren richtigen Typ in regelmäßigen Abfragen, aber dies does not happen in the aggregation pipeline, wie in Ausgabe # 1399 beschrieben.

Stattdessen müssen Sie das richtige Gießen tun manuell eingeben:

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

Dann können Sie sie in Ihrer Pipeline-Stufe verwenden:

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

Der Grund ist, weil Aggregation Pipelines „typisch“ das ändern Dokumentstruktur, und daher macht Mungo keine Vermutung, dass das "Schema" für das Dokument in irgendeiner gegebenen Pipeline-Stufe gilt.

Es ist strittig, dass die "erste" Pipeline-Stufe, wenn es eine $match Bühne ist, dies tun sollte, da das Dokument tatsächlich nicht geändert wird. Aber im Moment passiert das nicht so.

Alle Werte, die möglicherweise "Zeichenfolgen" oder zumindest nicht der richtige BSON-Typ sind, müssen manuell umgewandelt werden, damit sie übereinstimmen.

+0

Das ist es, es funktioniert jetzt. aber normalerweise werfe ich die ID als String in findOneAndUpdate oder andere Abfrage, und es funktioniert gut, ist das Problem nur in Aggregat geschehen? –

+1

@MuhammadFasalirRahman Dies ist genau, was ich mit beantwortet habe. Ein '.find()' kann das 'Schema' verwenden, das natürlich einen Standardtyp von' ObjectId' für das '_id' Feld hat. Aggregations-Pipelines ** ** verwenden ** nicht das Schema, wie ich eigentlich schon erklärt habe. –

+0

Dies funktioniert nicht in Mungo 5 –

Verwandte Themen