Source: query/update.js

/*! update.js */

/**
 * This mixin provides
 * [update()]{@linkcode KagoDB#update} and
 * [findAndModify()]{@linkcode KagoDB#findAndModify}
 * methods.
 *
 * @class update
 * @mixin
 * @see http://docs.mongodb.org/manual/reference/operator/#update-operators
 * @example
 * var collection = new KagoDB(opts);
 *
 * var query = {
 *   name: 'apple'
 * };
 * var update = {
 *   $inc: {
 *     stock: -1
 *   }
 * };
 * collection.update(query, update, null, function(err){
 *   console.log(err);
 * });
 */

module.exports = function() {
  var mixin = {};
  mixin.update = _update;
  return mixin;
};

/**
 * This updates item(s) which matches the specified query.
 * $set, $unset, $inc, $push, $pull, $rename operators are available as update parameters.
 *
 * @method KagoDB.prototype.update
 * @param {Object|Function} condition - query selector or function
 * @param {Object|Function} update - update operator or function
 * @param {Object} [options] - update options: multi
 * @param {Function} [callback] - function(err) {}
 * @see http://docs.mongodb.org/manual/reference/operator/#update-operators
 * @example
 * var collection = new KagoDB();
 *
 * var query = {
 *   name: 'John'
 * };
 * var update = {
 *   $set: {
 *     child: 'Sean'
 *   },
 *   $inc: {
 *     age: 1
 *   }
 * };
 * var options = {
 *   multi: false
 * };
 * collection.update(query, update, options, function(err){
 *   console.log(err);
 * });
 */

function _update(condition, update, options, callback) {
  var collection = this;
  var pkey = this.pkey();
  var onwrite;

  if ('function' == typeof options && !callback) {
    callback = options;
    options = null;
  }

  update = this.obop().update(update);
  options = options || {};
  callback = callback || NOP;

  if (!pkey) {
    throw new Error('primary key not defined');
  }

  if (options.multi) {
    this.find(condition).each(updater);
  } else {
    onwrite = callback;
    this.findOne(condition, updater);
  }

  return this;

  function updater(err, item) {
    if (err) return callback(err);
    if (!item) return callback();
    var id = item[pkey];
    if (update) item = update(item);
    collection.write(id, item, onwrite);
  }
}

function NOP() {}