function _ensureIndexes(model, options, callback) {
  const indexes = Array.isArray(options?.toCreate) ? options.toCreate : model.schema.indexes();
  let indexError;

  options = options || {};
  const done = function(err) {
    if (err && !model.$caught) {
      model.emit('error', err);
    }
    model.emit('index', err || indexError);
    callback && callback(err || indexError);
  };

  for (const index of indexes) {
    if (isDefaultIdIndex(index)) {
      utils.warn('mongoose: Cannot specify a custom index on `_id` for ' +
        'model name "' + model.modelName + '", ' +
        'MongoDB does not allow overwriting the default `_id` index. See ' +
        'https://bit.ly/mongodb-id-index');
    }
  }

  if (!indexes.length) {
    immediate(function() {
      done();
    });
    return;
  }
  // Indexes are created one-by-one to support how MongoDB < 2.4 deals
  // with background indexes.

  const indexSingleDone = function(err, fields, options, name) {
    model.emit('index-single-done', err, fields, options, name);
  };
  const indexSingleStart = function(fields, options) {
    model.emit('index-single-start', fields, options);
  };

  const baseSchema = model.schema._baseSchema;
  const baseSchemaIndexes = baseSchema ? baseSchema.indexes() : [];

  immediate(function() {
    // If buffering is off, do this manually.
    if (options._automatic && !model.collection.collection) {
      model.collection.addQueue(create, []);
    } else {
      create();
    }
  });


  function create() {
    if (options._automatic) {
      if (model.schema.options.autoIndex === false ||
          (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) {
        return done();
      }
    }

    const index = indexes.shift();
    if (!index) {
      return done();
    }
    if (options._automatic && index[1]._autoIndex === false) {
      return create();
    }

    if (baseSchemaIndexes.find(i => utils.deepEqual(i, index))) {
      return create();
    }

    const indexFields = clone(index[0]);
    const indexOptions = clone(index[1]);

    delete indexOptions._autoIndex;
    decorateDiscriminatorIndexOptions(model.schema, indexOptions);
    applyWriteConcern(model.schema, indexOptions);
    applySchemaCollation(indexFields, indexOptions, model.schema.options);

    indexSingleStart(indexFields, options);

    if ('background' in options) {
      indexOptions.background = options.background;
    }

    // Just in case `createIndex()` throws a sync error
    let promise = null;
    try {
      promise = model.collection.createIndex(indexFields, indexOptions);
    } catch (err) {
      if (!indexError) {
        indexError = err;
      }
      if (!model.$caught) {
        model.emit('error', err);
      }

      indexSingleDone(err, indexFields, indexOptions);
      create();
      return;
    }

    promise.then(
      name => {
        indexSingleDone(null, indexFields, indexOptions, name);
        create();
      },
      err => {
        if (!indexError) {
          indexError = err;
        }
        if (!model.$caught) {
          model.emit('error', err);
        }

        indexSingleDone(err, indexFields, indexOptions);
        create();
      }
    );
  }
}
Similar to `ensureIndexes()`, except for it uses the [`createIndex`](https://mongodb.github.io/node-mongodb-native/4.9/classes/Db.html#createIndex)
function.

@param {Object} [options] internal options
@return {Promise}
@api public