Пример #1
0
def obj_from_oplog(data, _filter, projection=None, pop_fields=None):
    _id = None
    obj = {}

    _filter = _filter or {}

    op = _.get(data, 'op')
    ns = '.'.join(_.get(data, 'ns').split('.')[1:])
    if op == 'i':
        i_obj = copy.deepcopy(_.get(data, 'o') or {})
        _id = _.get(i_obj, '_id', None)
        if i_obj and dict_filter(i_obj, _filter, ns):
            i_obj.pop('_id', None)
            obj = i_obj
    elif op == 'u':
        _id = _.get(data, 'o2._id')
        u_obj = copy.deepcopy(_.get(data, 'o') or {})
        if u_obj:
            if not _.get(u_obj, '$set'):
                if u_obj and dict_filter(u_obj, _filter, ns):
                    obj = u_obj
                    obj.pop('_id', None)
            else:
                U_filter = dict(_filter, **{'_id': _id})
                collection = models.get_collection(ns)
                if collection.count(U_filter) > 0:
                    obj = _.get(u_obj, '$set')
                    obj.pop('_id', None)
    elif op == 'd':
        _id = _.get(data, 'o._id')

    if _id and pop_fields:
        collection = models.get_collection(ns)
        collection.__class__ = BaseModel
        obj = collection.populate_one(filter={'_id': _id},
                                      projection=projection,
                                      pop_fields=pop_fields)
        obj.pop('_id', None)

    return str(_id) if _id else None, obj or {}
Пример #2
0
    def __populate(self, local_data_list, pop_fields, field_value_filter=lambda v: v):
        # 获取外键collection,并判断是否存在
        foreign_collection = models.get_collection(pop_fields.get('from'))

        # 主键set,用于存储主键(不重复)
        local_field_set = set()
        local_field = pop_fields.get('local_field')
        _as = pop_fields.get('as') or local_field
        # 收集主键
        for local_data in local_data_list:
            local_field_set.add(field_value_filter(_.get(local_data, local_field)))

        # 无主键,返回主collection数据
        if len(local_field_set) <= 0:
            return local_data_list

        foreign_field = pop_fields.get('foreign_field')
        foreign_data_dict = dict()
        f_filter = {pop_fields.get('foreign_field'): {'$in': list(local_field_set)}}

        # 查询外键collection,并形成dict
        foreign_data_list = list(foreign_collection.find(filter=f_filter, projection=pop_fields.get('projection')))

        # 递归查询populate数据
        recursion_pop_fields = pop_fields.get('pop_fields')
        if recursion_pop_fields:
            for key, value in recursion_pop_fields.items():
                foreign_data_list = self.__populate(foreign_data_list, value, field_value_filter)

        for foreign_data in foreign_data_list:
            if isinstance(_.get(foreign_data, foreign_field), list):
                for arr_id in _.get(foreign_data, foreign_field):
                    foreign_data_dict[field_value_filter(arr_id)] = foreign_data
            else:
                foreign_data_dict[field_value_filter(_.get(foreign_data, foreign_field))] = foreign_data

        # 匹配外键,并将数据添加到主collection
        for local_data in local_data_list:
            local_data[_as] = foreign_data_dict.get(field_value_filter(_.get(local_data, local_field))) or {}

        return local_data_list
Пример #3
0
def dict_filter(data, _filter, ns):
    """
        判断数据是否符合筛选器, 支持mongo的filter语法, 支持两种模式
            1. 简单模式: {key:value}, 直接判断处理
            2. 复杂模式: filter中存在复杂语义, 直接通过数据库进行查询
    """
    if data and _filter:
        for key, value in _filter.items():
            if key.find('$') > -1 or key.find('{') > -1 or str(value).find(
                    '$') > -1 or str(value).find('{') > -1:
                # 复杂语义
                return models.get_collection(ns).count(_filter) > 0

            # 简单语义
            v = _.get(data, key)
            if isinstance(v, list):
                if not _.includes(v, value):
                    return False
            elif isinstance(v, type(value)):
                if v != value:
                    return False

    return True