def create_index(self, field_or_spec, unique=False, wait=True, **kwargs):
        """Creates an index on the given field or with the given specification,
        if necessary.

        Indexes enable efficient sorting, merging, and other such operations.

        Frame-level fields can be indexed by prepending ``"frames."`` to the
        field name.

        .. note::

            If an index with the same field(s) but different order(s) already
            exists, no new index will be created.

            Use :meth:`drop_index` to drop an existing index first if you wish
            to replace an existing index with new properties.

        .. note::

            If you are indexing a single field and it already has a unique
            constraint, it will be retained regardless of the ``unique`` value
            you specify. Conversely, if the given field already has a
            non-unique index but you requested a unique index, the existing
            index will be replaced with a unique index.

            Use :meth:`drop_index` to drop an existing index first if you wish
            to replace an existing index with new properties.

        Args:
            field_or_spec: the field name, ``embedded.field.name``, or index
                specification list. See
                :meth:`pymongo:pymongo.collection.Collection.create_index` for
                supported values
            unique (False): whether to add a uniqueness constraint to the index
            wait (True): whether to wait for index creation to finish
            **kwargs: optional keyword arguments for
                :meth:`pymongo:pymongo.collection.Collection.create_index`

        Returns:
            the name of the index
        """
        if etau.is_str(field_or_spec):
            input_spec = [(field_or_spec, 1)]
        else:
            input_spec = list(field_or_spec)

        single_field_index = len(input_spec) == 1
        index_info = self.get_index_information()

        # For single field indexes, provide special handling based on `unique`
        # constraint
        if single_field_index:
            field = input_spec[0][0]

            if field in index_info:
                _unique = index_info[field].get("unique", False)
                if _unique or (unique == _unique):
                    # Satisfactory index already exists
                    return field

                _field, is_frame_field = self._handle_frame_field(field)

                if _field == "id":
                    # For some reason ID indexes are not reported by
                    # `get_index_information()` as being unique like other
                    # manually created indexes, but they are, so nothing needs
                    # to be done here
                    return field

                if _field in self._get_default_indexes(frames=is_frame_field):
                    raise ValueError(
                        "Cannot modify default index '%s'" % field
                    )

                # We need to drop existing index and replace with a unique one
                self.drop_index(field)

        is_frame_fields = []
        index_spec = []
        for field, option in input_spec:
            has_frames = self._has_frame_fields()
            if field != "$**" and (
                not has_frames or field != "frames.$**"
            ):  # global wildcard indexes
                self._validate_root_field(field, include_private=True)

            _field, _, _ = self._handle_id_fields(field)
            _field, is_frame_field = self._handle_frame_field(_field)
            is_frame_fields.append(is_frame_field)
            index_spec.append((_field, option))

        if len(set(is_frame_fields)) > 1:
            raise ValueError(
                "Fields in a compound index must be either all sample-level "
                "or all frame-level fields"
            )

        is_frame_index = all(is_frame_fields)

        if single_field_index:
            index_name = input_spec[0][0]
        else:
            index_name = "_".join("%s_%s" % (f, o) for f, o in index_spec)

        if is_frame_index:
            index_name = self._FRAMES_PREFIX + index_name

        normalize = lambda name: name.replace("-1", "1")
        _index_name = normalize(index_name)
        if any(_index_name == normalize(name) for name in index_info.keys()):
            # Satisfactory index already exists
            return index_name

        # Setting `w=0` sets `acknowledged=False` in pymongo
        write_concern = None if wait else WriteConcern(w=0)

        if is_frame_index:
            coll = self._dataset._get_frame_collection(
                write_concern=write_concern
            )
        else:
            coll = self._dataset._get_sample_collection(
                write_concern=write_concern
            )

        name = coll.create_index(index_spec, unique=unique, **kwargs)

        if single_field_index:
            name = input_spec[0][0]
        elif is_frame_index:
            name = self._FRAMES_PREFIX + name

        return name
Creates an index on the given field or with the given specification,
        if necessary.

        Indexes enable efficient sorting, merging, and other such operations.

        Frame-level fields can be indexed by prepending ``"frames."`` to the
        field name.

        .. note::

            If an index with the same field(s) but different order(s) already
            exists, no new index will be created.

            Use :meth:`drop_index` to drop an existing index first if you wish
            to replace an existing index with new properties.

        .. note::

            If you are indexing a single field and it already has a unique
            constraint, it will be retained regardless of the ``unique`` value
            you specify. Conversely, if the given field already has a
            non-unique index but you requested a unique index, the existing
            index will be replaced with a unique index.

            Use :meth:`drop_index` to drop an existing index first if you wish
            to replace an existing index with new properties.

        Args:
            field_or_spec: the field name, ``embedded.field.name``, or index
                specification list. See
                :meth:`pymongo:pymongo.collection.Collection.create_index` for
                supported values
            unique (False): whether to add a uniqueness constraint to the index
            wait (True): whether to wait for index creation to finish
            **kwargs: optional keyword arguments for
                :meth:`pymongo:pymongo.collection.Collection.create_index`

        Returns:
            the name of the index
        
fiftyone/core/collections.py