Loopback: User.create([newUserData]) does not return the final instances with id's

Created on 20 Aug 2015  Â·  24Comments  Â·  Source: strongloop/loopback

I'm creating a bunch of fake data in a boot script on the backend for testing, and one of the things I want to do is pass an array of new user data into User.create(). Passing a single new user object behaves as expected, returning the newly created user with id property injected. But passing an array simply returns the original array, not an array of the newly created user instances (i.e. there are no id's). The call is working successfully otherwise, because when I check the database the users have been created and have id's.

Note that I'm using the promise functionality of the API, i.e. User.create(newUsersDataArray).then(function(users) {...})

stale

Most helpful comment

Still experiencing this issue! Any update ?

All 24 comments

Can you provide a link to a test project on GitHub? See https://github.com/strongloop/loopback/wiki/Issues#bug-report

This is my first time raising an issue and making a test repo for it, hope this is enough to clarify:

https://github.com/einarbmag/loopback-issue-arrays

I made a boot/ script to generate users, and it shows how the response fails to give the new instance id's when passing an array of new users, but only when using promises, not when using callbacks. The promise response simply echoes the input array.

Thanks! I will try to reproduce the issue on my end and let you know how it goes.

Same issue here. It's not that it doesn't return the id, the problem is that it doesn't return a promise or a thenable, i.e.: When calling Model.create(array), (array being a js array) that same array is what gets returned.

The behaviour is not consistent with the one get when calling Model.create(data) where data is an object.

I'd expect it to return a promise or an array of promises (or thenables).

This weird behaviour got me too. Even though it's easy to workaround using map, if it's not fixed, I think it should at least be documented.

Are you guys still running into issues here? I believe this should be fixed since promise support was implemented recently.

I'm still running into the issue.

User.create([
    {email: '[email protected]', password: 'admin'}
  ], function(err, user) {
    // user.id === undefined
  });

package.json:

"dependencies": {
  "compression": "^1.6.1",
  "cors": "^2.7.1",
  "loopback": "^2.28.0",
  "loopback-boot": "^2.18.1",
  "loopback-component-explorer": "^2.5.0",
  "loopback-component-storage": "^1.8.0",
  "loopback-connector-mongodb": "^1.14.0",
  "loopback-datasource-juggler": "^2.46.0",
  "kerberos": "^0.0.19",
  "serve-favicon": "^2.3.0"
}

user.json:

  "base": "User",
  "idInjection": true

NodeJS 5.11

Few days ago, I have the same issue. But I found the solution.

Actually, Model.create returns created instance with the id field after saved in database. These problems are related with migration of the model.

When I use model's datasource connected with 'memory', these problems are not happened. But when I changed the datasource to RDB (in my case, postgreSQL), these issue occur. So, why?

The reason is that loopback doesn't automatically migrate the user defined model in initializing stage. But when ExampleModel.create method called, it doesn't return error message with "Cann't find database table named examplemodel", but just return instance object stored in memory. This object is not saved in RDB because there are no corresponding table. So it didn't have model Id neither, but no error message returned. It causes developers to think that "Look, I create the ExampleModel instance and it would be saved my RDB. But where's the Id?".

So, I solved this problem with migrating the model. In my case, I wrote automigrate method in boot script.

Ref.
https://docs.strongloop.com/display/public/LB/Creating+a+database+schema+from+models

Solved my problem. Thanks!
Is it bad to write this for every model?

I'm not sure. But it is forced to do that until loopback support auto migrate model in boot up stage.

Glad you guys got it resolved. @casamia918 is right, models are not automigrated unless you tell it to. This would be no problem for NoSQL DBs like mongodb (which create collections on the fly as needed).

I'm not sure. But it is forced to do that until loopback support auto migrate model in boot up stage.

The issue is that automigrate wipes the table data, so if you automigrate each time during app boot up, you will lose data. So it probably makes more sense to have a migration script in something like ./bin in your project and run the migrations once, then boot your LB app and use it as normal. Otherwise, use auto-update.

@raymondfeng Do you have any suggestions on what the intended typical workflow is? Auto-migrating each time the app boots up doesn't seem logical to me for apps in prod.

@superkhau I think that loopback needs to support model migration at the "model configuration" level (known as server/model-config.json) if it can't find corresponding db table . Or, modify automigrate method to takes options. (E.g. "preserveExistingTable"). In this way, automigrate method can be more safe method.

As you said, current automigrate method must be carefully used because it wipes out the already stored data. But loopback beginner user often forgot to setup db. So 2 problematic cases are possibly happen.

1) Like this issue, new beginner user who didn't create db table can suffer these kind of issue.
2) If some user solve these problem using automigrate method in boot script, it means that they makes potential danger that they have to remove the automigrate method before launching the app. Imagine a careless developer who forgot to remove the automigrate method. When the application updated, the whole existing data gone away.

P.S.
For the beginner user, automigrate method is first intruduced in this guide page.
https://docs.strongloop.com/display/public/LB/Create+new+models
But there are no warning message about wiping out of automigrate method in this page. So it would be better to add a short warning message of automigrate method.
Or, more kind way is, revise that guide to use automigrate "not in boot script" but in "bin script", As superkhau said.

What you describe is exactly what I'm thinking to (the dangerous parts for newcomers).

Your proposed solution makes sense to me too, ie. if table exists in model-config.json and hasn't be automigrated during boot up, automigrate it (of course we would need a config to turn this behaviour on/off for backwards compatibility too). Would you like to submit a PR?

@raymondfeng What do you think about the feature proposed by @casamia918?

I am experiencing the original issue described but only in nested promises:

  // Boot/Seed script
  var data = [{
    name: 'foo'
  }]
  Model.create(data) // I return a promise
  .then(function(created1) {
    console.log(created1); // Outputs with ids
    return Model.create(data); // I return the data array...
  })
  .then(function(created2) {
    console.log(created2); // Outputs the original data only, no ids
  })

output:

Web server listening at: http://0.0.0.0:3000
Browse your REST API at http://0.0.0.0:3000/explorer
[{name: 'foo', 
  id: 1}]
[{name: 'foo'}]

As mentioned, if I look in the data store or do a query, both models 1 and 2 were created, it's just the second create did not return a promise, only the original array.

Tried with both in memory and PostgreSQL data sources.

Hello everyone, struggling with similar issue, I have a some models generated from postgresql db using looback-connector postgresql. Id column of these models is a auto incremented integer column of postgresql db.

1) I have a remote method added on one of persisted models, where i perform simple update or insert(upsert).
Car.CreateOrUpdateCar = function (carobj, req) { Car.upsert(Carobj, function (err, Car) { if (err) console.log(err); else { req(err, Car); } }); };

2) have added a remote hook to execute after this remote method.

   Car.afterRemote('CreateOrUpdateCar', function (context, remoteMethodOutput, next) {

//Remaining code goes here
next();
});

3) I want to use Id of newly inserted row in step (1), in the remote hook mentioned in step (2)

Object returned by upsert is same as that of object being inserted. This is a persisted model, and i think i do not need to migrate it.

This is how my model json is defined
"name": "car",
"base": "PersistedModel",
"idInjection": false,
"options": {
"validateUpsert": true
},
"postgresql": {
"schema": "public",
"table": "mstCar"
},
},
"acls": [],
"methods": {}
}

Id column is defined as:

"id": {
"type": "Number",
"id": true,
"required": false,
"index": true,
"length": null,
"precision": 32,
"scale": 0,
"generated": true,
"postgresql": {
"columnName": "Id",
"dataType": "integer",
"dataLength": null,
"dataPrecision": 32,
"dataScale": 0,
"nullable": "NO"
},
"_selectable": false
}

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.

Still experiencing this issue! Any update ?

I still experiencing this issue? Any update?

Hello Jetson,

Greetings,

Thanks for writing back.

We have changed our approach for this particular use case. Will not be able
to comment on its resolution. However, will try implementing it again soon.

Will write you back once I do so.

Thanks and Regards,
Ganesh Mahajan

On 20-Nov-2017 9:10 AM, "Jerson" notifications@github.com wrote:

I still experiencing this issue? Any update?

—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/strongloop/loopback/issues/1610#issuecomment-345583423,
or mute the thread
https://github.com/notifications/unsubscribe-auth/APydMs0SlRj5eeonxBLvtl_H3ol3GblGks5s4PSWgaJpZM4FvEpe
.

Thanks

Still experiencing this issue! Any update ?

Still the same issue, a year after..

Any fix update this issue?

Was this page helpful?
0 / 5 - 0 ratings