async function _updateThunk(op) {
  this._applyTranslateAliases();

  this._castConditions();

  // Check for empty/invalid filter with requireFilter option
  checkRequireFilter(this._conditions, this.options);

  _castArrayFilters(this);

  if (this.error() != null) {
    throw this.error();
  }

  const castedQuery = this._conditions;
  const options = this._optionsForExec(this.model);

  this._update = clone(this._update, options);
  const isOverwriting = op === 'replaceOne';
  if (isOverwriting) {
    this._update = new this.model(this._update, null, true);
  } else {
    this._update = this._castUpdate(this._update);

    if (this._update == null || Object.keys(this._update).length === 0) {
      return { acknowledged: false };
    }

    const _opts = Object.assign({}, options, {
      setDefaultsOnInsert: this._mongooseOptions.setDefaultsOnInsert
    });
    this._update = setDefaultsOnInsert(this._conditions, this.model.schema,
      this._update, _opts);
  }

  if (Array.isArray(options.arrayFilters)) {
    options.arrayFilters = removeUnusedArrayFilters(this._update, options.arrayFilters);
  }

  const runValidators = _getOption(this, 'runValidators', false);
  if (runValidators) {
    await this.validate(this._update, options, isOverwriting);
  }

  if (this._update.toBSON) {
    this._update = this._update.toBSON();
  }

  return this.mongooseCollection[op](castedQuery, this._update, options);
}
Override mquery.prototype._mergeUpdate to handle mongoose objects in
updates.

@param {Object} doc
@method _mergeUpdate
@memberOf Query
@instance
@api private