def _dereference(cls, documents, references):
        for path, projection in references.items():
            if '$ref' not in projection:
                continue
            ids = set()
            for document in documents:
                value = cls._path_to_value(path, document)
                if not value:
                    continue
                if isinstance(value, list):
                    ids.update(value)
                elif isinstance(value, dict):
                    ids.update(value.values())
                else:
                    ids.add(value)
            ref = projection.pop('$ref')
            frames = ref.many(
                {'_id': {'$in': list(ids)}},
                projection=projection
                )
            frames = {f._id: f for f in frames}
            for document in documents:
                value = cls._path_to_value(path, document)
                if not value:
                    continue
                if isinstance(value, list):
                    value = [frames[id] for id in value if id in frames]
                elif isinstance(value, dict):
                    value = {key: frames.get(id) for key, id in value.items()}
                else:
                    value = frames.get(value, None)
                child_document = document
                keys = cls._path_to_keys(path)
                for key in keys[:-1]:
                    child_document = child_document[key]
                child_document[keys[-1]] = value