Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undefined properties are set to null in Mongodb #30

Closed
danivek opened this issue Oct 18, 2016 · 5 comments
Closed

Undefined properties are set to null in Mongodb #30

danivek opened this issue Oct 18, 2016 · 5 comments
Assignees

Comments

@danivek
Copy link

danivek commented Oct 18, 2016

Description

versions :
js-data: 3.0.0-rc.6
js-data-mongodb : 1.0.0-rc.1

Steps to reproduce

Here is my model schema :

{
  "type": "object",
  "properties": {
    "a": {
      "type": "string"
    },
    "b": {
      "type": "string"
    }
  },
  "required": ["a"],
  "additionalProperties": false
}

When i insert or update not all the properties of my model (example with only property "a" : {a: "a"}), the others properties are set to undefined by js-data. So the input props of methods create or update looks like :

{
  a: "a",
  b: undefined
}

The problem is that the Node.js mongodb driver, insert null in the database for all the undefined properties. So when you just want to update property "a", the previous value of property "b" is erase by a null value.

The workaround solution i found, is to remove all undefined properties of the object in methods beforeCreate and beforeUpdate on the adapter. But i think it could be made directly on insert or update methods.

// Workaround to avoid undefined values to be set to null in MongoDB
const adapter = new MongoDBAdapter({
  uri: config.MONGODB_URI,
  beforeUpdate(mapper, id, props) {
    const removeUndefined = (obj) => {
      Object.keys(obj).forEach(key =>
        (obj[key] && typeof obj[key] === 'object') && removeUndefined(obj[key]) ||
        (obj[key] === undefined) && delete obj[key]
      );
      return obj;
    };
    removeUndefined(props);
  }
});

Solution can be found here : http://stackoverflow.com/questions/286141/remove-blank-attributes-from-an-object-in-javascript. It should be recursive and only remove undefined properties.

Any thoughts ?

Thanks!

@crobinson42
Copy link
Member

@jmdobry is this caused by the adapter or js-data v3 schema validation?

@jmdobry
Copy link
Member

jmdobry commented Oct 20, 2016

Interesting, I'll have to give it a try. If the MongoDB driver was sane, it would treat undefined as "property does not exist", instead of converting it to null.

@danivek
Copy link
Author

danivek commented Oct 20, 2016

@crobinson42, @jmdobry

I look at the MongoDB Driver documentation for DB class, there is an option that can be set to the DB instance ignoreUndefined. I don't know why it is set to false by default...

So an other possible solution that works is to set ignoreUndefined to true on connect method:

MongoClient.connect(opts.uri, {
      db: {
        ignoreUndefined: true
      }
    }, (err, db) => {
      if (err) {
        return reject(err)
      }
      this._db = db
      resolve(db)
    })

I will try to investigate further why this behavior is not the default one.

@danivek
Copy link
Author

danivek commented Oct 20, 2016

@crobinson42
Copy link
Member

@danivek thx for the leg work on the mongo driver opts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants