MongoDB and undefined values

Hey guys,
I’m having a little issue with MongoDB and a query with a undefined field. For example, we use this query:

let oldTransaction = Transaction.findOne({transactionApiId:this.transactionApiId,transactionId, requestId});

In some cases, transactionId is undefined. The problem is, that this query returns a document that has a defined transactionId value. So the query gets changed to:

let oldTransaction = Transaction.findOne({transactionApiId:this.transactionApiId, requestId});

It ignores the transactionId field completely. Is this the normal behavior? In the console, the query can’t be executed due to

"errmsg" : "cannot compare to undefined",

Mongoose converts all undefined values to null values. But Meteor seems to remove the fields. Thats some behavior I didn’t expect.

A couple of things:

  1. any command issued on the client gets converted to an EJSON string. Part of that process removes any key where the value is undefined so {key: undefined} -> {}
  2. In Mongo, you can use {key: {$exists: false}} which will allow you to find entries that have undefined values, rather than excluding the key.
  3. You may want to look here https://docs.mongodb.com/manual/reference/bson-types/ though the undefined type is deprecated

Hello,

Bumping this old topic since it’s probably important to understand the behavior of selectors with undefined values.

In a mongo console if you issue a query that contains an undefined in the selector you get the error mentioned by @XTA:

db.getCollection('myCollection').find({ name: undefined })
// "errmsg" : "cannot compare to undefined"

However using the collection either wrapped by meteor collections or using the driver directly (as exposed by rawCollection()) the attribute is ignored.

So for example in this server side code, the undefined value omits the attribute from the selector turning it into a naked selector:

col.find({}).count(); // -> 57
col.find({ name: /test/ }).count(); // -> 8
col.find({ name: null }).count(); // -> 0
col.find({ name: undefined }).count(); // -> 57

I think it’s important to be aware of this to avoid leaking documents when a constraint is not properly checked for undefined or initialized as null.

Removing undefined from the selectors is not something that Meteor does - it’s an option of the MongoDB driver. It has changed in 1.6.1.

2 Likes