Partially modify a document by providing a subset of its data fields to be modified

        :param db:
            Handle to the MongoDB database

        :param key:
            The primary key of the database object being modified. Usually its ``_id``

        :param data:
            The data set to be modified

        :type data:
            ``dict``

async def modify(cls, db, key, data: dict):
        '''
        Partially modify a document by providing a subset of its data fields to be modified

        :param db:
            Handle to the MongoDB database

        :param key:
            The primary key of the database object being modified. Usually its ``_id``

        :param data:
            The data set to be modified

        :type data:
            ``dict``
        '''

        if data is None:
            raise BadRequest('Failed to modify document. No data fields to modify')
        # validate partial data
        cls._validate(data)

        query = {cls.primary_key: key}
        for i in cls.connection_retries():
            try:
                result = await db[cls.get_collection_name()].find_one_and_update(
                    filter=query,
                    update={'$set': data},
                    return_document=ReturnDocument.AFTER
                )
                if result:
                    updated_obj = cls.create_model(result)
                    updated_obj._db = db
                    # emit post save
                    asyncio.ensure_future(post_save.send(
                        sender=cls,
                        db=db,
                        instance=updated_obj,
                        created=False)
                    )
                    return updated_obj
                return None
            except ConnectionFailure as ex:
                exceed = await cls.check_reconnect_tries_and_wait(i, 'update')
                if exceed:
                    raise ex