HMR
HMR

Reputation: 39270

Model.aggregate gives me different results as in the mongo console (none for mongoose)

When I execute the following in the console I get one nameID and a min max.

db.prices.aggregate([
  {"$match":{ nameID: { '$in': [ ObjectId('longid') ] } } }//replaced the actual value with longid
  ,{"$group":{"_id":"$nameID","nameID":{"$first": "$nameID"} ,"min":{"$min":"$price"},"max":{"$max":"$price"}}}
  ,{"$sort":{"min":1}}
  ,{"$limit":5}
])

When in mongoose I get an empty array:

Price.aggregate([
  {"$match":{ nameID: { '$in': [ 'longid' ] } }}//replaced the actual value with longid
  ,{"$group":{"_id":"$nameID","nameID":{"$first": "$nameID"} ,"min":{"$min":"$price"},"max":{"$max":"$price"}}}
  ,{"$sort":{"min":1}}
  ,{"$limit":5}
  ],function(){}//needs a callback passed or no promise is returned
).then(function(res){
  console.log('got a totals:',res);//res is [] here
  return Price.find({ nameID: { '$in': [ 'longid' ] } }}).exec();
}).then(function(res){
  console.log(res.length);//yes, got 3 records
  console.log(res[0]['price']);//yes, the price

Doing a Price.find with the query gets me 3 records.

Am I missing something or is this a known problem with mongoose?

[UPDATE]

With aggregate I cannot pass the id as a string so converted to ObjectId and it worked. Here is an example how:

 Price.aggregate([   
    {"$match":{ nameID: { '$in': [ 
        new mongoose.Types.ObjectId('longid')//replaced the actual value with longid
      ] 
    } 
 }}
 ...

Upvotes: 0

Views: 1797

Answers (1)

Neil Lunn
Neil Lunn

Reputation: 151112

Oops. From your last comment to my last comment you have highlighted the problem here. Mongoose will "inspect" and convert "types" based on the applied schema to the model in most cases for operations. It cannot and "will not" do this in aggregation pipelines. So you need to do this:

var ObjectID = require("mongodb").ObjectID;

var actual_hex_string; // as received from input parameters

// then
Price.aggregate([
    {"$match":{ 
         "nameID": { 
             "$in": [ ObjectID(actual_hex_string) ]
          }
    }}
    (...) // the rest of the pipeline

Also $in seems not to be appropriate here unless you are intending to use an actual "array" of possible ( and already converted ) ObjectID values here. Don't make the common mistake of thinking "nameID" is an "array" therefore you must use $in. MongoDB does not care if this is an array or a single value. $in is for "multiple matches" in an $or context for the same field. A simple equality match works just as well for an "array" in the document.

Upvotes: 4

Related Questions