mlegenhausen,
I tried this and it didn't seem to work correctly. But then I found your
workaround <https://github.com/LearnBoost/mongoose/issues/633>. This code
is working now:
// in my schema definition:
AccountSchema.statics.findAndModify = function (query, sort, doc, options,
callback) {
return this.collection.findAndModify(query, sort, doc, options, callback);
};
// in my model service:
var findOrCreate = exports.findOrCreate = function (data, callback) {
if (!data.source) {
return callback(new ParamError('Missing account.source.'));
}
if (!data.external_id) {
return callback(new ParamError('Missing account.external_id'));
}
var upsertDoc = new Account(data).toObject();
delete upsertDoc._id;
Account.findAndModify({
source: data.source,
external_id: data.external_id
}, [], upsertDoc, {
"new": true,
"upsert": true
}, function (err, doc) {
if (err) {
return callback(err);
}
if (!doc) {
return callback();
}
var account = new Account();
account.init(doc, function (err) {
if (err) {
return callback(err);
}
return callback(null, account);
});
});
};
Thanks for your help!
On Sunday, July 29, 2012 4:24:16 AM UTC-7, mlegenhausen wrote:
>
> Why you do not use the findAndModify method? This method can create an
> document when it is not find via the upsert: true parameter. This method
> has the advantage to be atomic like a transaction and you get no problems
> when you run multiple node process which execute your findOrCreate method.
>
> Am Sonntag, 29. Juli 2012 03:12:40 UTC+2 schrieb Jaime Morales:
>>
>> Hi,
>>
>> I am running into an issue trying to run multiple findOrCreate methods in
>> parallel.
>>
>> Here is the code:
>>
>> var findOrCreate = exports.findOrCreate = function (data, callback) {
>> if (!data.source) {
>> return callback(new ParamError('Missing account.source.'));
>> }
>> if (!data.external_id) {
>> return callback(new ParamError('Missing account.external_id'));
>> }
>>
>> Account.findOne({
>> source: data.source,
>> external_id: data.external_id
>> }, function (err, account) {
>> if (err) {
>> return callback(err);
>> }
>> if (account) {
>> return callback(err, account);
>> }
>> account = new Account(data);
>> account.save(function (err) {
>> return callback(err, account);
>> });
>>
>> });
>>
>> };
>>
>> The issue is that I may have multiple queries for the same
>> source/external_id combo. I am using async.parallel to handle them. But
>> since the callbacks in mongoose are pushed onto the next tick, I end up in
>> a situation where
>>
>> 1. a find is performed (pushing the create to the next tick)
>> 2. another find is performed for the same source/external_id (pushing
>> the create to the next tick)
>> 3. a create is performed (for the first find)
>> 4. an attempt is made to create again, but this time a duplicate key
>> error is thrown (since I already created that account)
>>
>> I originally tried to get around this by doing an upsert instead of find
>> or create, but that didn't work since I need access the the resulting item.
>> I am not sure what the best way to handle this scenario is. any ideas?
>>
>
--
Job Board: http://jobs.nodejs.org/
Posting guidelines:
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
You received this message because you are subscribed to the Google
Groups "nodejs" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en