Skip to content

Instantly share code, notes, and snippets.

@btkostner
Last active January 30, 2016 07:15
Show Gist options
  • Select an option

  • Save btkostner/d97f767afc6f8d0b4f28 to your computer and use it in GitHub Desktop.

Select an option

Save btkostner/d97f767afc6f8d0b4f28 to your computer and use it in GitHub Desktop.
upsert (update or create) a nested array in mongoose near atomicly without save function
import mongoose from 'mongoose';
import _ from 'lodash';
import dotize from 'dotize';
ApplicationSchema.methods.upsertRelease = function(query, object) {
const application = this;
// Create an object from query using dot notation instead of objects ('releases.github.id')
const dotQuery = dotize.convert(query, 'releases');
// Create an object of values to update to, uses mongoose's $ operator
const dotUpdate = dotize.convert(object, 'releases.$');
// Create a new object of dotQuery, but with mongodb's not operator for value
const notDotQuery = _.mapValues(dotQuery, value => ({ $ne: value }));
return Promise.all([ // Return two promises, one for update, and one for insert
Application.update(_.extend({ // Find an application with same _id, and includes release query
_id: application._id,
}, dotQuery), dotUpdate), // Use generated dotUpdate object for updating
Application.update(_.extend({ // Find an application that has _id but does NOT include release (avoids adding when already exists)
_id: application._id,
}, notDotQuery), {
$addToSet: {
releases: object, // Push new release into array
},
}),
]);
}
@btkostner
Copy link
Author

This function comes in handy when using promises that run in parallel. It does not use any .save() functions, so it will never be using out of date information to calculate existence. It depends on one of the functions failing while the other succeeds, hence the not query in the second function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment