Sails: Sails v1.0 & sails-mongo: Can't create a document with custom id value

Created on 2 Mar 2017  ·  19Comments  ·  Source: balderdashy/sails

_From @Josebaseba on February 28, 2017 3:53_

sails: v1.0.0-27
sails-mongo: 1.0.0-4

I can't create a document with a custom id like: '58959f6f6e6d1b620acc7a00', it always gets overwritten by another "random" ID. I tried in all the possible ways but I couldn't.

Plus, if you have your models migration option set to 'alter' the id of all the objects keep changing, so if you have a model with an association to that other document you lose it.

It took me like an hour to realize about what was happening :)

_Copied from original issue: balderdashy/sails-mongo#456_

bug v1.x

Most helpful comment

@algope This should be all set with the latest beta of Waterline and sails-mongo. The easiest way to get it in your project is:

npm cache clean
npm install sails-hook-orm@beta --force
npm install sails-mongo@beta --force

Then you should be able to set dontUseObjectIds: true in your model, and set up the id attribute however you want, e.g.:

js // api/models/User.js module.exports = { dontUseObjectIds: true, attributes: { id: { type: 'number', columnName: '_id' }, // <-- still need to set `columnName`! name: { type: 'string' }, ...etc... } }

Give that a whirl and let us know if it works for you!

All 19 comments

@Josebaseba Thanks for posting, we'll take a look as soon as possible. In the meantime, if you haven’t already, please carefully read the issue contribution guidelines and double-check for any missing information above. In particular, please ensure that this issue is about a stability or performance bug with a documented feature; and make sure you’ve included detailed instructions on how to reproduce the bug from a clean install. Finally, don’t forget to include the version of Node.js you tested with, as well as your version of Sails or Waterline, and of any relevant standalone adapters/generators/hooks.

Thank you!

_From @sgress454 on March 1, 2017 22:54_

Hi @Josebaseba -- we're aware of the issue and are working on it. We'll post back when there's a patch!

This is fixed as of sails-mongo v1.0.0-5.

Hello @sgress454, thanks for the update!

I've been testing it with version v1.0.0-5 and I'm still having the same issue when trying to insert a document with a custom id: AdapterError: Unexpected error from database adapter: Invalid primary key value provided for 'id'. Cannot interpret '600000' as a Mongo id.

@algope There's a new flag you'll be able to use for this in Sails v1-- I know sgress454 is @looking at making sure it's in the docs now, so I'll let him cover the details, just wanted to give you the heads up in the mean time

@mikermcneil Awesome, thank you for the quick reply.

@algope This should be all set with the latest beta of Waterline and sails-mongo. The easiest way to get it in your project is:

npm cache clean
npm install sails-hook-orm@beta --force
npm install sails-mongo@beta --force

Then you should be able to set dontUseObjectIds: true in your model, and set up the id attribute however you want, e.g.:

js // api/models/User.js module.exports = { dontUseObjectIds: true, attributes: { id: { type: 'number', columnName: '_id' }, // <-- still need to set `columnName`! name: { type: 'string' }, ...etc... } }

Give that a whirl and let us know if it works for you!

@sgress454 Confirmed! It works like a charm 😍
Thanks a lot for the work!

I don't know if it's linked but by using User.create(fields) i got the warning but it still creates the document. It looks like an ObjectID:

Warning: Records sent back from a database adapter should always have a valid property
that corresponds with the primary key attribute (`id`).  But in this result set,
after transforming columnNames back to attribute names for model `user`,
there is a record with a missing or invalid `id`.
Record:

{ id: 5c10d38c63e37b4b189e141a,
  createdAt: 1544606604697,
  updatedAt: 1544606604697,
  email: '[email protected]',
  emailPaypal: '',
  password: '$2a$10$xIL1WggFc523uIt8ogokA.JSRRAwrtl5ethg2tuzfIaslbVrL/9Wi',
  fullName: 'John Doe',
  isAdmin: false,
  isVerified: false,
  passwordResetToken: '',
  passwordResetTokenExpiresAt: 0,
  createdWithIp: '::ffff:127.0.0.1',
  credit: 0,
  lastSeenAt: 0 }

> You are seeing this warning because there are records in your database that don't
> match up with your models.  This is often the result of a model definition being
> changed without also migrating leftover data.  But it could also be because records
> were added or modified in your database from somewhere outside of Sails/Waterline
> (e.g. phpmyadmin, or another app).  In either case, to make this warning go away,
> you have a few options.  First of all, you could change your model definition so
> that it matches the existing records in your database.  Or you could update/destroy
> the old records in your database; either by hand, or using a migration script.
>
> (For example, to wipe all data, you might just use `migrate: drop`.)
>
> More rarely, this warning could mean there is a bug in the adapter itself.  If you
> believe that is the case, then please contact the maintainer of this adapter by opening
> an issue, or visit http://sailsjs.com/support for help.

sails version : ^1.1.0
sails-mongo version : ^1.0.1

My config/models.js :

module.exports.models = {
  schema: true,
  migrate: 'drop',
  dontUseObjectIds: true,
  attributes: {
    id: { type: 'number', columnName: '_id', autoIncrement: true, },
  }
   dataEncryptionKeys: {
    default: 'xxx'
  },
  cascadeOnDestroy: true
};

And my User.js :

module.exports = {
  dontUseObjectIds: true,
  attributes: {
    createdAt: { type: 'number', autoCreatedAt: true, },
    updatedAt: { type: 'number', autoUpdatedAt: true, },

    //....
  }
}

And when I want to create the user :

var newUserRecord = await User.create({
      email: newEmailAddress,
      emailPaypal: newEmailPaypal,
      password: await sails.helpers.passwords.hashPassword(inputs.password),
      fullName: inputs.fullName,
      createdWithIp: this.req.ip,
    })
    .intercept('E_UNIQUE', 'emailAlreadyInUse')
    .intercept({name: 'UsageError'}, 'invalid')
    .fetch();

Do you guys have an idea ?

Hey @SwiTool, id: { type: 'string', columnName: '_id' } that's the proper configuration for the mongo adapter.

Hello @Josebaseba I got the same exact error message with string type.
It still looks like an ObjectID :

{ id: 5c112f310733356f4fe1e872,
  createdAt: 1544630065818,
  updatedAt: 1544630065818,
  email: '[email protected]',
  emailPaypal: '',
  password: '$2a$10$nDpJxfhNHToUDBDf/CNpo.15zimQzrJW7gym9cd.BB5iNAzoeIXju',
  fullName: 'John Doe',
  isAdmin: false,
  isVerified: false,
  passwordResetToken: '',
  passwordResetTokenExpiresAt: 0,
  createdWithIp: '::ffff:127.0.0.1',
  credit: 0,
  lastSeenAt: 0 }

Don't use the dontUseObjectIds flag.

Yes but I need it to test the relations of my models and the logic integrations.
Without dontUseObjectIds I can't predict ObjectIDs so can't establish connections between models.

For logic integrations I don't need this, but still. if it's not possible i'll just comment every model test and won't load the fixtures that are associated to them.

You can create a custom id without that flag:

var newUserRecord = await User.create({
      id: 'objectidstring',
      email: newEmailAddress,
      emailPaypal: newEmailPaypal,
      password: await sails.helpers.passwords.hashPassword(inputs.password),
      fullName: inputs.fullName,
      createdWithIp: this.req.ip,
    })
    .intercept('E_UNIQUE', 'emailAlreadyInUse')
    .intercept({name: 'UsageError'}, 'invalid')
    .fetch();

Sorry to bother you but I already tried and ended with :

  0 passing (3s)
  1 failing

  1) "before all" hook:
     AdapterError: Unexpected error from database adapter: Invalid primary key value provided for `id`.  Cannot interpret `1` as a Mongo id.
(Usually, this is the result of a bug in application logic.)
For more info on Mongo ids, see:
• https://docs.mongodb.com/manual/reference/bson-types/#objectid

The fixture loaded is this one :

[
  {
    "model":"user",
    "items":[
      {
        "id": "1",
        "email":"[email protected]",
        "fullName": "Foo Bar",
        "password": "123",
        "createdWithIp": "::1"
      },
      {
        "id": "2",
        "email":"[email protected]",
        "fullName": "Bar Foo",
        "password": "123",
        "createdWithIp": "::1"
      }
    ]
  }
]

You need to use a real mongo id, something like this: "5af2d22aa7cec4083c4c4c4d"

Indeed. Thanks a lot :)

You need to use a real mongo id, something like this: "5af2d22aa7cec4083c4c4c4d"

Could you expatiate what you mean by a real mongo id please? I am experiencing the same issue

@mykoman sure, if you want to create a new document with a custom _id, it must be a valid mongoId.

You can't use a custom type _id, it must follow mongoId rules, but you can generate an _id like this:

https://docs.mongodb.com/manual/reference/method/ObjectId/#generate-a-new-objectid

To access that method from the sails object layer:

sails.getDatastore().driver.mongodb.ObjectID()

Was this page helpful?
0 / 5 - 0 ratings