7

I'm having the following code:

              var objectid = infos[i].id;
              var name = infos[i].name;
              return collection.aggregate([
                {$match: {app: new ObjectId(objectid)}},
                {$group: {_id: "$uid", amt: {$sum: 1}}}
              ])

Previously this code was working fine, but recently I started getting the below stacktrace in sails:

error: TypeError: Argument must be a string
    at TypeError (native)
    at Buffer.write (buffer.js:791:21)
    at serializeObjectId (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:242:10)
    at serializeInto (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:699:17)
    at serializeObject (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:280:18)
    at serializeInto (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:705:17)
    at serializeObject (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:280:18)
    at serializeInto (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:551:17)
    at serializeObject (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:280:18)
    at serializeInto (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/parser/serializer.js:705:17)
    at serialize (/Users/user/git/pivot/code/node_modules/sails-mongo/node_modules/bson/lib/bson/bson.js:47:27)

It's complaining because of the ObjectId which I imported like so:

var ObjectId = require('mongodb').ObjectID;

As I said before, this was working fine but not anymore. I'm really confused. If I put objectId as a string it will not return any results. If I leave it as is (as it was working before) it throws exceptions. What is the issue here?

I have read the below :

https://docs.mongodb.com/v3.0/reference/operator/aggregation/cmp/#exp._S_cmp

I'm able to do this in robomongo:

 db.getCollection("openevent").aggregate([
                {$match: {app: new ObjectId(OBJECT_ID) }},
                {$group: {_id: "$uid", amt: {$sum: 1}}}
              ])

Using the same values as above. What am I doing wrong??

I see the following for sails-mongo:

└─┬ sails-mongo@0.12.1
  └─┬ mongodb@2.1.6
    └── mongodb-core@1.3.1
KVISH
  • 12,923
  • 17
  • 86
  • 162
  • It looks like it is expecting to find a Buffer. What about 'new ObjectId(new Buffer(String(objectid)))'? – HeadCode Jul 27 '16 at 04:18
  • Doesn't work :( `Argument passed in must be a single String of 12 bytes or a string of 24 hex characters` – KVISH Jul 27 '16 at 04:27
  • Can you console.log the objectid after the first line above? – HeadCode Jul 27 '16 at 04:29
  • Three values: `57424c8908d4af812c77a77e`, `5748eac6c35b3145141b6463`, `577212b6f05adb1a3ad16399` – KVISH Jul 27 '16 at 04:30
  • It's in a loop, one after another. – KVISH Jul 27 '16 at 04:31
  • I think the problem is the loop. The database stuff will be asynchronous but you have used a local variable as an argument, which will either have changed by the next iteration or be long gone by the time the database function returns. See this post: http://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop – HeadCode Jul 27 '16 at 04:50
  • I do them in a promise, for each loop. I think it's fine. It seems to be something else. And it's working in production! Locally i'm using a mac and on production its Ubuntu. – KVISH Jul 27 '16 at 05:02
  • Can you try doing `{$match: {app: new ObjectId(objectid.toString())}}`? This may help you. – Shrabanee Jul 27 '16 at 05:46
  • Try doing `toString()` inside ObjectId. – Shrabanee Jul 27 '16 at 05:47
  • Nope -- tried that as well! Also, `objectid` is a string in my case. – KVISH Jul 27 '16 at 05:52

2 Answers2

12

I have no idea why this is even an answer, but I'll post it.

Previously I had this:

var ObjectId = require('mongodb').ObjectID;

I changed to this:

var ObjectId = require('sails-mongo/node_modules/mongodb').ObjectID;

And somehow that made all the difference.

KVISH
  • 12,923
  • 17
  • 86
  • 162
8

For posterity's sake, this is usually due to compatibility issues between versions of mongo. MongoDB driver 2.2 uses mongodb-core 2.0 (and bson 0.5) whereas MongoDB driver 2.1 uses mongodb-core 1.3 and bson 0.4. If you try to use a MongoDB driver 2.1 ObjectId with MongoDB driver 2.2 you'll get this error.

vkarpov15
  • 3,614
  • 24
  • 21