Moonridge icon indicating copy to clipboard operation
Moonridge copied to clipboard

Update with populated field

Open mazco-luaris opened this issue 8 years ago • 3 comments

I just encountered an issue that I think turned out to be two different issues.

using this (partial) Schema var MrQuotes = this.MR.model('Mrquotes', { quote_number: Number, quote_version: Number, broker_id: { type: Schema.Types.ObjectId, ref: 'Brokers' }, mrClient_ids: [{type: Schema.Types.ObjectId, ref: 'Mrclients' }], stat: String, create_date: Date,....

I am able to retrieve records with all manner of queries against the model client side. No problems, in fact it works incredibly well. When I add a new object to the mrClient_ids array and call update that also works. However I found that if I sliced an item out of the array and called update the previous state was serialized to the database without the desired change. I tracked this down to mr-rpc-methods and compared toUpdate with doc after the _.merge(doc, toUpdate) and found that underscore was not merging the changes. I noticed that since I had been using populate that the objects looked very different and I guessed that lodash was probably getting confused. As you know the original document consists of the array of object ID's and not the fully populated document. So I tried an experiment. Before calling update I did a foreach on the collection, extracted just the _id's into an array, assigned them to the model and then ran the update. I actually expected this to work but it also didn't. I still don't know why. So I thought about replacing lodash for this, just to simplify things and used plain JS as described here: https://plainjs.com/javascript/utilities/merge-two-javascript-objects-19/

Using that technique I was then able to update both adding and removing objects. In either case I have retained the approach of updating the model with only the id's as that seems to be a cleaner solution rather than hoping that everything in between handles the nested objects correctly.

Any thoughts on this?

Thanks and by the way great work on this project. It's incredibly useful.

/W

mazco-luaris avatar Apr 09 '16 20:04 mazco-luaris

FYI I accidentally posted that using a client's github account. My apologies. I am actually the OP for the above.

WolfieWerewolf avatar Apr 09 '16 20:04 WolfieWerewolf

@WolfieWerewolf thanks for the report. Lodash certainly can have some unwanted behaviour. We should come up with a simple testcase and include it in the fix. Can you give me a sample of how the data looks like before you call update on your model and how do you expect them to look after that update?

capaj avatar Apr 10 '16 10:04 capaj

@capaj thanks for your positive reply, I'm happy to help in any way I can. This is all dummy data so no privacy concerns; I'm getting my output from logging inside mr-rpc.methods.js.

In this case there were two mrClients associated with the quote. Aaron Wolf and Andrew Wolf as seen here in:

previousVersion mrClient_ids: [ 56520dd781715c8057c3c768, 56520dd781715c8057c3c783 ] }

toUpdate shows the object, which had been populated, with Andrew Wolf removed; it contains only Aaron Wolf.

mrClient_ids: [ { _id: '56520dd781715c8057c3c768', rider_id: '56520dd481715c8057c3b5b9', linkedin_id: 'This is some address', facebook_id: '......', skype_id: '[email protected]', email: '[email protected]', post_code: '4250', state: 'QLD', locality: 'SomeLocality', street_name: 'Jemmy Rd', house_number: '2318', rider: true, occupation: 'Senior Party Coordinator', mobile: '0455655543', landline: '0566677766', lastname: 'Wolf', firstname: 'Aaron', __v: 5, mrQuote_ids: [Object], mrRider_id: [Object], mrRider: true } ] }

Notice that, as it is fully populated it contains all of the data and not just the _id that is to be stored in the mrClient_ids array.

Here is doc after the _merge { mrClient_ids: [ 56520dd781715c8057c3c768, 56520dd781715c8057c3c783 ],

It has stripped all of the populated data but has failed to remove the _id for Andrew Wolf. So the update was not successful.

Now here is the output using the fix I described above for the same operation:

previousVersion mrClient_ids: [ 56520dd781715c8057c3c768, 56520dd781715c8057c3c783 ] }

toUpdate mrClient_ids: [ '56520dd781715c8057c3c768' ] }

doc { mrClient_ids: [ 56520dd781715c8057c3c768 ],

Note that in addition to replacing _merge with the plainjs snippet I provided, server side, I also performed the following "cleaning operation" on the client before calling update. This is an AngularJs front end but should be pretty self explanatory. The following is in my $scope.serialize = function(){}

var mrClientIds = []; $scope.quoteRow.mrClient_ids.forEach(function(clientIds){ mrClientIds.push(clientIds._id); }) $scope.quoteRow.mrClient_ids = mrClientIds

mrService.mrquoteModel.update($scope.quoteRow);

mrService is just an Angular factory service that I put together to wrap the MoonRidge client so I can inject it throughout my app.

The best possible outcome would be to somehow inform the MoonRidge server about which objects have been populated and have it perform the "cleaning" operation that I have done manually, to strip out only the objectId's that the schema is expecting and replace all the populated data, before attempting to do the merge.

The model had previously been populated as follows:

var query = mrService.mrquoteModel.query() .find({ _id: id}) .populate('mrClient_ids') .populate('broker_id') .populate('mrRider_id') var promise = query.exec();

      promise.then(function (doc) {
      $scope.quoteRow = doc[0];  //It's only expecting one result.
      .........

Before attempting to make any serious changes to your framework I thought it best to open this discussion as you will certainly have a better idea for how to approach this than I would.

If anything is unclear or you require any further information please let me know.

Kind Regards

/W

WolfieWerewolf avatar Apr 10 '16 12:04 WolfieWerewolf