def merge_field_schema(
        cls,
        schema,
        expand_schema=True,
        recursive=True,
        validate=True,
        overwrite=False,
    ):
        """Merges the field schema into this document.

        Args:
            schema: a dict mapping field names or ``embedded.field.names`` to
                :class:`fiftyone.core.fields.Field` instances
            expand_schema (True): whether to add new fields to the schema
                (True) or simply validate that fields already exist with
                consistent types (False)
            recursive (True): whether to recursively merge embedded document
                fields
            validate (True): whether to validate fields against existing fields
                at the same path
            overwrite (False): whether to overwrite the editable metadata of
                existing fields

        Returns:
            True/False whether any new fields were added

        Raises:
            ValueError: if a field in the schema is not compliant with an
                existing field of the same name or a new field is found but
                ``expand_schema == False``
        """
        dataset = cls._dataset
        dataset_doc = dataset._doc
        media_type = dataset.media_type
        is_frame_field = cls._is_frames_doc
        now = datetime.utcnow()

        new_schema = {}
        new_metadata = {}

        for path, field in schema.items():
            _new_schema, _new_metadata = cls._merge_field(
                path,
                field,
                validate=validate,
                recursive=recursive,
                overwrite=overwrite,
            )

            if _new_schema:
                new_schema.update(_new_schema)

            if _new_metadata:
                new_metadata.update(_new_metadata)

        if new_schema and not expand_schema:
            raise ValueError(
                "%s fields %s do not exist"
                % (cls._doc_name(), list(new_schema.keys()))
            )

        if not new_schema and not new_metadata:
            return False

        # This fixes https://github.com/voxel51/fiftyone/issues/3185
        # @todo improve list field updates in general so this isn't necessary
        cls._reload_fields()

        for path in new_schema.keys():
            _, _, _, root_doc = cls._parse_path(path)
            if root_doc is not None and getattr(root_doc, "read_only", False):
                root = path.rsplit(".", 1)[0]
                raise ValueError("Cannot edit read-only field '%s'" % root)

            validate_field_name(
                path,
                media_type=media_type,
                is_frame_field=is_frame_field,
            )

        # Silently skip updating metadata of any read-only fields
        for path in list(new_metadata.keys()):
            field = cls._get_field(path, allow_missing=True)
            if field is not None and (
                not isinstance(field, fof.Field)
                or getattr(field, "read_only", False)
            ):
                del new_metadata[path]

        for path, field in new_schema.items():
            # Special syntax for declaring the subfield of a ListField
            if path.endswith("[]"):
                path = path[:-2]
                field = fof.ListField(field=field)

            cls._add_field_schema(path, field, created_at=now)

        for path, d in new_metadata.items():
            cls._update_field_metadata(path, d)

        dataset_doc.save()

        return True
Merges the field schema into this document.

        Args:
            schema: a dict mapping field names or ``embedded.field.names`` to
                :class:`fiftyone.core.fields.Field` instances
            expand_schema (True): whether to add new fields to the schema
                (True) or simply validate that fields already exist with
                consistent types (False)
            recursive (True): whether to recursively merge embedded document
                fields
            validate (True): whether to validate fields against existing fields
                at the same path
            overwrite (False): whether to overwrite the editable metadata of
                existing fields

        Returns:
            True/False whether any new fields were added

        Raises:
            ValueError: if a field in the schema is not compliant with an
                existing field of the same name or a new field is found but
                ``expand_schema == False``
        
fiftyone/core/odm/mixins.py