Exemple #1
0
    def query(self, entity, limit=None, offset=0, limit_fields=None,
              order_by=None, desc=False, filters={},
              substring_filters=[], search_related=False, related_field_names=None,
              **kw):

        if '_id' in filters:
            try:
                filters['_id'] = ObjectId(filters['_id'])
            except InvalidId:
                pass

        if search_related:
            # Values for related fields contain the text to search
            filters = self._modify_params_for_related_searches(entity, filters,
                                                               view_names=related_field_names,
                                                               substrings=substring_filters)
        filters = self._modify_params_for_relationships(entity, filters)

        for field in substring_filters:
            if self.is_string(entity, field):
                filters[field] = {'$regex': re.compile(re.escape(filters[field]), re.IGNORECASE)}

        iter = entity.query.find(filters)
        if offset:
            iter = iter.skip(int(offset))
        if limit is not None:
            iter = iter.limit(int(limit))

        if order_by is not None:
            if not isinstance(order_by, (tuple, list)):
                order_by = [order_by]

            if not isinstance(desc, (tuple, list)):
                desc = [desc]

            sorting = [(field, DESCENDING if sort_descending else ASCENDING) for field, sort_descending in
                       zip_longest(order_by, desc)]
            iter.sort(sorting)

        count = iter.count()
        return count, iter.all()
Exemple #2
0
    def query(self, entity, limit=None, offset=0, limit_fields=None,
              order_by=None, desc=False, filters={},
              substring_filters=[], search_related=False, related_field_names=None,
              **kw):

        if '_id' in filters:
            try:
                filters['_id'] = ObjectId(filters['_id'])
            except InvalidId:
                pass

        if search_related:
            # Values for related fields contain the text to search
            filters = self._modify_params_for_related_searches(entity, filters,
                                                               view_names=related_field_names,
                                                               substrings=substring_filters)
        filters = self._modify_params_for_relationships(entity, filters)

        for field in substring_filters:
            if self.is_string(entity, field):
                filters[field] = {'$regex': re.compile(re.escape(filters[field]), re.IGNORECASE)}

        count = entity.query.find(filters).count()

        pipeline = []
        if filters:
            pipeline.append({'$match': filters})

        discarded = []
        if order_by is not None:
            if not isinstance(order_by, (tuple, list)):
                order_by = [order_by]

            if not isinstance(desc, (tuple, list)):
                desc = [desc]

            sorting = SON()
            for sort_by, sort_descending in zip_longest(order_by, desc):
                sort_order = DESCENDING if sort_descending else ASCENDING
                if self.is_relation(entity, sort_by):
                    relationship = getattr(entity, sort_by)
                    join = relationship.join
                    my_foreign_key = relationship._detect_foreign_keys(relationship.mapper,
                                                                    join.rel_cls,
                                                                    False)
                    rel_foreign_key = relationship._detect_foreign_keys(mapper(relationship.related),
                                                                        join.own_cls,
                                                                        False)
                    related_col_name = mapper(relationship.related).collection.m.collection_name
                    embedded_results_field = '__%s_%s' % (related_col_name, uuid.uuid4().hex)
                    discarded.append(embedded_results_field)
                    if my_foreign_key:
                        pipeline.append({'$lookup': {
                            'from': related_col_name,
                            'localField': my_foreign_key[0].name,
                            'foreignField': '_id',
                            'as': embedded_results_field
                        }})
                    else:
                        pipeline.append({'$lookup': {
                            'from': related_col_name,
                            'localField': '_id',
                            'foreignField': rel_foreign_key[0].name,
                            'as': embedded_results_field
                        }})
                    sorting['%s.%s' % (
                        embedded_results_field, 
                        self.get_view_field_name(relationship.related, related_field_names or [])
                    )] = sort_order
                else:
                    sorting[sort_by] = sort_order
            if sorting:
                pipeline.append({'$sort': sorting})

        if offset:
            pipeline.append({'$skip': int(offset)})
        if limit is not None:
            pipeline.append({'$limit': int(limit)})

        if discarded:
            pipeline.append({'$project': {f: False for f in discarded}})

        results = ODMCursor(self.session, entity, entity.query.aggregate(pipeline))
        return count, results.all()
Exemple #3
0
    def query(self,
              entity,
              limit=None,
              offset=None,
              limit_fields=None,
              order_by=None,
              desc=False,
              filters={},
              substring_filters=[],
              search_related=False,
              related_field_names=None,
              **kw):
        entity = resolve_entity(entity)
        query = self.session.query(entity)

        filters = self._modify_params_for_dates(entity, filters)

        if search_related:
            # Values for related fields contain the text to search
            filters = self._modify_params_for_related_searches(
                entity,
                filters,
                view_names=related_field_names,
                substrings=substring_filters)
        else:
            # Values for related fields contain the primary key
            filters = self._modify_params_for_relationships(entity, filters)

        for field_name, value in filters.items():
            field = getattr(entity, field_name)
            if self.is_relation(entity, field_name) and isinstance(
                    value, list):
                related_class = self._get_related_class(entity, field_name)
                related_pk = self.get_primary_field(related_class)
                related_pk_col = getattr(related_class, related_pk)
                related_pk_values = (getattr(v, related_pk) for v in value)
                if self._relates_many(entity, field_name):
                    field_filter = field.any(
                        related_pk_col.in_(related_pk_values))
                else:
                    field_filter = field.has(
                        related_pk_col.in_(related_pk_values))
                query = query.filter(field_filter)
            elif field_name in substring_filters and self.is_string(
                    entity, field_name):
                escaped_value = self._escape_like(value.lower())
                query = query.filter(
                    func.lower(field).contains(escaped_value, escape='*'))
            else:
                query = query.filter(field == value)

        count = query.count()

        if order_by is not None:
            if not isinstance(order_by, (tuple, list)):
                order_by = [order_by]

            if not isinstance(desc, (tuple, list)):
                desc = [desc]

            for sort_by, sort_descending in zip_longest(order_by, desc):
                if self.is_relation(entity, sort_by):
                    mapper = class_mapper(entity)
                    class_ = self._get_related_class(entity, sort_by)
                    query = query.outerjoin(sort_by)
                    f = self.get_view_field_name(class_, related_field_names)
                    field = self.get_field(class_, f)
                else:
                    field = self.get_field(entity, sort_by)

                if sort_descending:
                    field = _desc(field)
                query = query.order_by(field)

        if offset is not None:
            query = query.offset(offset)
        if limit is not None:
            query = query.limit(limit)

        objs = query.all()

        return count, objs
Exemple #4
0
    def query(self, entity, limit=None, offset=None, limit_fields=None,
              order_by=None, desc=False, filters={},
              substring_filters=[], search_related=False, related_field_names=None,
              **kw):
        entity = resolve_entity(entity)
        query = self.session.query(entity)

        filters = self._modify_params_for_dates(entity, filters)

        if search_related:
            # Values for related fields contain the text to search
            filters = self._modify_params_for_related_searches(entity, filters,
                                                               view_names=related_field_names,
                                                               substrings=substring_filters)
        else:
            # Values for related fields contain the primary key
            filters = self._modify_params_for_relationships(entity, filters)

        for field_name, value in filters.items():
            field = getattr(entity, field_name)
            if self.is_relation(entity, field_name) and isinstance(value, list):
                related_class = self._get_related_class(entity, field_name)
                related_pk = self.get_primary_field(related_class)
                related_pk_col = getattr(related_class, related_pk)
                related_pk_values = (getattr(v, related_pk) for v in value)
                if self._relates_many(entity, field_name):
                    field_filter = field.any(related_pk_col.in_(related_pk_values))
                else:
                    field_filter = field.has(related_pk_col.in_(related_pk_values))
                query = query.filter(field_filter)
            elif field_name in substring_filters and self.is_string(entity, field_name):
                escaped_value = self._escape_like(value.lower())
                query = query.filter(func.lower(field).contains(escaped_value, escape='*'))
            else:
                query = query.filter(field==value)

        count = query.count()

        if order_by is not None:
            if not isinstance(order_by, (tuple, list)):
                order_by = [order_by]

            if not isinstance(desc, (tuple, list)):
                desc = [desc]

            for sort_by, sort_descending in zip_longest(order_by, desc):
                if self.is_relation(entity, sort_by):
                    mapper = class_mapper(entity)
                    class_ = self._get_related_class(entity, sort_by)
                    query = query.outerjoin(sort_by)
                    f = self.get_view_field_name(class_, related_field_names)
                    field = self.get_field(class_, f)
                else:
                    field = self.get_field(entity, sort_by)

                if sort_descending:
                    field = _desc(field)
                query = query.order_by(field)

        if offset is not None:
            query = query.offset(offset)
        if limit is not None:
            query = query.limit(limit)

        objs = query.all()

        return count, objs
Exemple #5
0
    def query(self,
              entity,
              limit=None,
              offset=0,
              limit_fields=None,
              order_by=None,
              desc=False,
              filters={},
              substring_filters=[],
              search_related=False,
              related_field_names=None,
              **kw):

        if '_id' in filters:
            try:
                filters['_id'] = ObjectId(filters['_id'])
            except InvalidId:
                pass

        if search_related:
            # Values for related fields contain the text to search
            filters = self._modify_params_for_related_searches(
                entity,
                filters,
                view_names=related_field_names,
                substrings=substring_filters)
        filters = self._modify_params_for_relationships(entity, filters)

        for field in substring_filters:
            if self.is_string(entity, field):
                filters[field] = {
                    '$regex': re.compile(re.escape(filters[field]),
                                         re.IGNORECASE)
                }

        count = entity.query.find(filters).count()

        pipeline = []
        if filters:
            pipeline.append({'$match': filters})

        discarded = []
        if order_by is not None:
            if not isinstance(order_by, (tuple, list)):
                order_by = [order_by]

            if not isinstance(desc, (tuple, list)):
                desc = [desc]

            sorting = SON()
            for sort_by, sort_descending in zip_longest(order_by, desc):
                sort_order = DESCENDING if sort_descending else ASCENDING
                if self.is_relation(entity, sort_by):
                    relationship = getattr(entity, sort_by)
                    join = relationship.join
                    my_foreign_key = relationship._detect_foreign_keys(
                        relationship.mapper, join.rel_cls, False)
                    rel_foreign_key = relationship._detect_foreign_keys(
                        mapper(relationship.related), join.own_cls, False)
                    related_col_name = mapper(
                        relationship.related).collection.m.collection_name
                    embedded_results_field = '__%s_%s' % (related_col_name,
                                                          uuid.uuid4().hex)
                    discarded.append(embedded_results_field)
                    if my_foreign_key:
                        pipeline.append({
                            '$lookup': {
                                'from': related_col_name,
                                'localField': my_foreign_key[0].name,
                                'foreignField': '_id',
                                'as': embedded_results_field
                            }
                        })
                    else:
                        pipeline.append({
                            '$lookup': {
                                'from': related_col_name,
                                'localField': '_id',
                                'foreignField': rel_foreign_key[0].name,
                                'as': embedded_results_field
                            }
                        })
                    sorting['%s.%s' %
                            (embedded_results_field,
                             self.get_view_field_name(
                                 relationship.related, related_field_names
                                 or []))] = sort_order
                else:
                    sorting[sort_by] = sort_order
            if sorting:
                pipeline.append({'$sort': sorting})

        if offset:
            pipeline.append({'$skip': int(offset)})
        if limit is not None:
            pipeline.append({'$limit': int(limit)})

        if discarded:
            pipeline.append({'$project': {f: False for f in discarded}})

        results = ODMCursor(self.session, entity,
                            entity.query.aggregate(pipeline))
        return count, results.all()