mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
Implement Collection.upsert().
Basically the same code as Collection.update(... { upsert: true }) except that
it returns an object with numberAffected and insertedId keys. remove() is back
to returning just the number affected, not an object, so that both update() and
remove() match the mongo api.
Untested.
This commit is contained in:
@@ -537,7 +537,7 @@ LocalCollection.prototype.remove = function (selector, callback) {
|
||||
LocalCollection._recomputeResults(query);
|
||||
});
|
||||
self._observeQueue.drain();
|
||||
var result = { numberAffected: remove.length };
|
||||
var result = remove.length;
|
||||
if (callback)
|
||||
Meteor.defer(function () {
|
||||
callback(null, result);
|
||||
|
||||
@@ -337,13 +337,24 @@ var throwIfSelectorIsNotId = function (selector, methodName) {
|
||||
// generating their result until the database has acknowledged
|
||||
// them. In the future maybe we should provide a flag to turn this
|
||||
// off.
|
||||
_.each(["insert", "update", "remove"], function (name) {
|
||||
_.each(["insert", "update", "remove", "upsert"], function (name) {
|
||||
Meteor.Collection.prototype[name] = function (/* arguments */) {
|
||||
var self = this;
|
||||
var args = _.toArray(arguments);
|
||||
var callback;
|
||||
var ret;
|
||||
|
||||
// Calling `Collection.upsert()` is just like calling `Collection.update()`
|
||||
// with upsert: true, except that we return the whole object with
|
||||
// `numberAffected` and `idInserted` keys. So we do the same thing as an
|
||||
// update, except that we save `isUpsert` to determine what to return when
|
||||
// we're done.
|
||||
var isUpsert = false;
|
||||
if (name === "upsert") {
|
||||
isUpsert = true;
|
||||
name = "update";
|
||||
}
|
||||
|
||||
if (args.length && args[args.length - 1] instanceof Function)
|
||||
callback = args.pop();
|
||||
|
||||
@@ -364,7 +375,9 @@ _.each(["insert", "update", "remove"], function (name) {
|
||||
args[0] = Meteor.Collection._rewriteSelector(args[0]);
|
||||
|
||||
if (name === "update") {
|
||||
var options = args[2];
|
||||
var options = _.clone(args[2]);
|
||||
if (isUpsert)
|
||||
options.upsert = true;
|
||||
if (options && options.upsert) {
|
||||
// set `insertedId` if absent. `insertedId` is a Meteor extension.
|
||||
if (options.insertedId) {
|
||||
@@ -427,8 +440,15 @@ _.each(["insert", "update", "remove"], function (name) {
|
||||
// On updates and removes, return whatever the collection returned; on
|
||||
// inserts, always return the id that we generated. If the user provided
|
||||
// a callback, then we expect queryRet to be undefined.
|
||||
if (name !== "insert")
|
||||
if (name !== "insert") {
|
||||
ret = queryRet;
|
||||
// Upsert updates return an object with the number affected and the
|
||||
// inserted id, but for update queries we only return the number
|
||||
// affected to match the mongo api. Meteor.Collection.upsert() can be
|
||||
// used to return the whole object.
|
||||
if (name === "update" && ! isUpsert)
|
||||
ret = ret.numberAffected;
|
||||
}
|
||||
} catch (e) {
|
||||
if (callback) {
|
||||
callback(e);
|
||||
|
||||
@@ -289,7 +289,7 @@ MongoConnection.prototype._remove = function (collection_name, selector,
|
||||
try {
|
||||
var collection = self._getCollection(collection_name);
|
||||
collection.remove(replaceTypes(selector, replaceMeteorAtomWithMongo),
|
||||
{safe: true}, numberAffectedCallback(callback));
|
||||
{safe: true}, callback);
|
||||
} catch (e) {
|
||||
write.committed();
|
||||
throw e;
|
||||
|
||||
Reference in New Issue
Block a user