function operand(self, where, delta, data, val, op) {
  // delta
  op || (op = '$set');
  if (!delta[op]) delta[op] = {};
  delta[op][data.path] = val;
  // disabled versioning?
  if (self.$__schema.options.versionKey === false) return;

  // path excluded from versioning?
  if (shouldSkipVersioning(self, data.path)) return;

  // already marked for versioning?
  if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return;

  if (self.$__schema.options.optimisticConcurrency) {
    return;
  }

  switch (op) {
    case '$set':
    case '$unset':
    case '$pop':
    case '$pull':
    case '$pullAll':
    case '$push':
    case '$addToSet':
    case '$inc':
      break;
    default:
      // nothing to do
      return;
  }

  // ensure updates sent with positional notation are
  // editing the correct array element.
  // only increment the version if an array position changes.
  // modifying elements of an array is ok if position does not change.
  if (op === '$push' || op === '$addToSet' || op === '$pullAll' || op === '$pull') {
    if (/\.\d+\.|\.\d+$/.test(data.path)) {
      self.$__.version = VERSION_ALL;
    } else {
      self.$__.version = VERSION_INC;
    }
  } else if (/^\$p/.test(op)) {
    // potentially changing array positions
    self.$__.version = VERSION_ALL;
  } else if (Array.isArray(val)) {
    // $set an array
    self.$__.version = VERSION_ALL;
  } else if (/\.\d+\.|\.\d+$/.test(data.path)) {
    // now handling $set, $unset
    // subpath of array
    self.$__.version = VERSION_WHERE;
  }
}
Apply the operation to the delta (update) clause as
well as track versioning for our where clause.

@param {Document} self
@param {Object} where Unused
@param {Object} delta
@param {Object} data
@param {Mixed} val
@param {String} [op]
@api private