0

I'm currently trying to learn NodeJS with MongoDB. I'm using mongoose to connect to a local installed version of MongoDB and am using mocha for my TTD.

I know the solution for this case, but not the reason why it is this way.

Let me explain: I create a schema and a model called MarioCharacter. I save this MarioCharacter to MongoDB using the .save function of mongoose. I want to find this MarioCharacter (there's only one, its variable is "newCharacter") in the database using it's id.

My code with mongoose and mocha looks like this:

  //Find a record by its ID
  it("Finds a record by id from the database", function(done) {

    MarioCharacter.findOne({_id: newCharacter._id}).then(function(result) {
      //Log the value
      console.log(newCharacter._id); // returns 5b277477fd8f6f2c6437e5bc
      console.log(result._id); // returns 5b277477fd8f6f2c6437e5bc

      //Log the type
      console.log(typeof newCharacter._id); // returns object
      console.log(typeof result._id); // returns object

      //Test fails - returns false
      assert(result._id === newCharacter._id);
      done();
    })
  });

The solution is to convert both to a string using the .toString() method, which means that both types don't seem to be the same, even tough it says object on both of them.

What is it that I don't get here? Are there also subtypes of objects or what?

Advena
  • 1,664
  • 2
  • 24
  • 45
  • 3
    Because you are comparing objects. It's javascript and has nothing to do with mongo. `console.log({a:1} === {a:1})` outputs false because theses are 2 different objects. – Alex Blex Jun 18 '18 at 11:11
  • You can read more from [Object comparison in JavaScript](https://stackoverflow.com/questions/1068834/object-comparison-in-javascript) to get a better idea. – Flynn Hou Jun 18 '18 at 11:56
  • If you really want to compare two BSON type of `_id`, you can do `assert.ok(result._id.equals(newCharacter._id))`, based on [Node.js MongoDB native driver](http://mongodb.github.io/node-mongodb-native/3.0/api/ObjectID.html). You can also go check Node.js MongoDB native driver's source code, you'll see even if you use the method `equals()`, under the hood, it's still doing `id1.toString() === id2.toString()` for you. – Flynn Hou Jun 18 '18 at 12:09
  • In other words, it's because both objects are referring to different objects, even if they have the same value? – Advena Jun 18 '18 at 13:56

1 Answers1

0

What you see from your // Log the value section is actually because Node.js MongoDB native driver has the overridden method toString() so that when you do console.log(), it'll print the toString() result on your console.

See this MDN post talking about Object.prototype.toString() and Node.js MongoDB native driver source code (line 189-197).


Originally, MongoDB's ObjectId is like this:

ObjectIds are small, likely unique, fast to generate, and ordered. ObjectId values consist of 12 bytes, where the first four bytes are a timestamp that reflect the ObjectId’s creation. Specifically:

  • a 4-byte value representing the seconds since the Unix epoch,
  • a 3-byte machine identifier,
  • a 2-byte process id, and
  • a 3-byte counter, starting with a random value.

—— Introduction to MongoDB > BSON types

Community
  • 1
  • 1
Flynn Hou
  • 429
  • 1
  • 6
  • 18
  • I know why the toString() works and how, but it's more why both Objects, the source of those strings are not the same – Advena Jun 18 '18 at 13:57
  • Do you mean `result._id.toString()` and `newCharacter._id.toString()` are not the same? Or `result._id` and `newCharacter._id`? If it's the latter, then it's because Objects `result._id` and `newCharacter._id` are two different Objects and they don't have the same references, and so they will not be entirely the same thing in JavaScript. – Flynn Hou Jun 18 '18 at 14:05