Ejemplo n.º 1
0
    def count(
            self,
            filter: Union[List[dict], dict],
            user: UserModel = None,
            permission: AccessControlPermission = None
    ) -> Union[Query, Pipeline]:
        """
        Count the number of documents in the stages
        Args:
            filter: filter requirement
            user: request user
            permission: acl permission

        Returns:
            Query with count stages.
        """
        self.clear()
        self.query = Pipeline([])

        if isinstance(filter, dict):
            self.query.append(self.match_(filter))
        elif isinstance(filter, list):
            for pipe in filter:
                self.query.append(pipe)

        if user and permission:
            self.query += (AccessControlQueryBuilder().build(
                group_id=PublicID(user.group_id), permission=permission))

        self.query.append(self.count_('total'))
        return self.query
Ejemplo n.º 2
0
    def build(self,
              search_term,
              user: UserModel = None,
              permission: AccessControlPermission = None,
              active_flag: bool = False,
              *args,
              **kwargs) -> Pipeline:
        """Build a pipeline query out of search search term"""

        regex = self.regex_('fields.value', f'{search_term}', 'ims')
        pipe_and = self.and_(
            [regex, {
                'active': {
                    "$eq": True
                }
            } if active_flag else {}])
        pipe_match = self.match_(pipe_and)

        # load reference fields in runtime.
        self.pipeline = SearchReferencesPipelineBuilder().build()

        # permission builds
        if user and permission:
            self.pipeline = [
                *self.pipeline, *(AccessControlQueryBuilder().build(
                    group_id=PublicID(user.group_id), permission=permission))
            ]
        self.add_pipe(pipe_match)
        self.add_pipe(
            {'$group': {
                "_id": {
                    'active': '$active'
                },
                'count': {
                    '$sum': 1
                }
            }})
        self.add_pipe({
            '$group': {
                '_id': 0,
                'levels': {
                    '$push': {
                        '_id': '$_id.active',
                        'count': '$count'
                    }
                },
                'total': {
                    '$sum': '$count'
                }
            }
        })
        self.add_pipe({'$unwind': '$levels'})
        self.add_pipe({'$sort': {"levels._id": -1}})
        self.add_pipe({
            '$group': {
                '_id': 0,
                'levels': {
                    '$push': {
                        'count': "$levels.count"
                    }
                },
                "total": {
                    '$avg': '$total'
                }
            }
        })
        self.add_pipe({
            '$project': {
                'total': "$total",
                'active': {
                    '$arrayElemAt': ["$levels", 0]
                },
                'inactive': {
                    '$arrayElemAt': ["$levels", 1]
                }
            }
        })
        self.add_pipe({
            '$project': {
                '_id': 0,
                'active': {
                    '$cond': [{
                        '$ifNull': ["$active", False]
                    }, '$active.count', 0]
                },
                'inactive': {
                    '$cond': [{
                        '$ifNull': ['$inactive', False]
                    }, '$inactive.count', 0]
                },
                'total': '$total'
            }
        })

        return self.pipeline
Ejemplo n.º 3
0
    def build(self,
              params: List[SearchParam],
              obj_manager: CmdbObjectManager = None,
              user: UserModel = None,
              permission: AccessControlPermission = None,
              active_flag: bool = False,
              *args,
              **kwargs) -> Pipeline:
        """Build a pipeline query out of frontend params"""
        # clear pipeline
        self.clear()

        # load reference fields in runtime.
        self.pipeline = SearchReferencesPipelineBuilder().build()

        # fetch only active objects
        if active_flag:
            self.add_pipe(self.match_({'active': {"$eq": True}}))

        # text builds
        text_params = [
            _ for _ in params
            if _.search_form == 'text' or _.search_form == 'regex'
        ]
        for param in text_params:
            regex = self.regex_('fields.value', param.search_text, 'ims')
            self.add_pipe(self.match_(regex))

        # type builds
        disjunction_query = []
        type_params = [_ for _ in params if _.search_form == 'type']
        for param in type_params:
            if param.settings and len(param.settings.get('types', [])) > 0:
                type_id_in = self.in_('type_id', param.settings['types'])
                if param.disjunction:
                    disjunction_query.append(type_id_in)
                else:
                    self.add_pipe(self.match_(type_id_in))
        if len(disjunction_query) > 0:
            self.add_pipe(self.match_(self.or_(disjunction_query)))

        # category builds
        category_params = [_ for _ in params if _.search_form == 'category']
        for param in category_params:
            if param.settings and len(param.settings.get('categories',
                                                         [])) > 0:
                categories = obj_manager.get_categories_by(
                    **self.regex_('label', param.search_text))
                for curr_category in categories:
                    type_id_in = self.in_('type_id', curr_category.types)
                    self.add_pipe(self.match_(type_id_in))

        # public builds
        id_params = [_ for _ in params if _.search_form == 'publicID']
        for param in id_params:
            self.add_pipe(self.match_({'public_id': int(param.search_text)}))

        # permission builds
        if user and permission:
            self.pipeline = [
                *self.pipeline, *(AccessControlQueryBuilder().build(
                    group_id=PublicID(user.group_id), permission=permission))
            ]
        return self.pipeline
Ejemplo n.º 4
0
    def build(self, filter: Union[List[dict], dict], limit: int, skip: int, sort: str, order: int,
              user: UserModel = None, permission: AccessControlPermission = None, *args, **kwargs) -> \
            Union[Query, Pipeline]:
        """
        Converts the parameters from the call to a mongodb aggregation pipeline
        Args:
            filter: dict or list of dict query/queries which the elements have to match.
            limit: max number of documents to return.
            skip: number of documents to skip first.
            sort: sort field
            order: sort order
            user: request user
            permission: AccessControlPermission
            *args:
            **kwargs:

        Returns:
            The `FrameworkQueryBuilder` query pipeline with the parameter contents.
        """
        self.clear()
        loading_dep_preset = [
            self.lookup_(_from='framework.types',
                         _local='type_id',
                         _foreign='public_id',
                         _as='type'),
            self.unwind_({'path': '$type'}),
            self.match_({'type': {
                '$ne': None
            }}),
            self.lookup_(_from='management.users',
                         _local='author_id',
                         _foreign='public_id',
                         _as='author'),
            self.unwind_({
                'path': '$author',
                'preserveNullAndEmptyArrays': True
            }),
            self.lookup_(_from='management.users',
                         _local='editor_id',
                         _foreign='public_id',
                         _as='editor'),
            self.unwind_({
                'path': '$editor',
                'preserveNullAndEmptyArrays': True
            }),
        ]
        self.query = Pipeline(loading_dep_preset)

        if isinstance(filter, dict):
            self.query.append(self.match_(filter))
        elif isinstance(filter, list):
            for pipe in filter:
                self.query.append(pipe)

        if user and permission:
            self.query += (AccessControlQueryBuilder().build(
                group_id=PublicID(user.group_id), permission=permission))

        if limit == 0:
            results_query = [self.skip_(limit)]
        else:
            results_query = [self.skip_(skip), self.limit_(limit)]

        # TODO: Remove nasty quick hack
        if sort.startswith('fields'):
            sort_value = sort[7:]
            self.query.append({
                '$addFields': {
                    'order': {
                        '$filter': {
                            'input': '$fields',
                            'as': 'fields',
                            'cond': {
                                '$eq': ['$$fields.name', sort_value]
                            }
                        }
                    }
                }
            })
            self.query.append({'$sort': {'order': order}})
        else:
            self.query.append(self.sort_(sort=sort, order=order))

        self.query += results_query
        return self.query
Ejemplo n.º 5
0
    def build(self, filter: Union[List[dict], dict], limit: int, skip: int, sort: str, order: int,
              user: UserModel = None, permission: AccessControlPermission = None, *args, **kwargs) -> \
            Union[Query, Pipeline]:
        """
        Converts the parameters from the call to a mongodb aggregation pipeline
        Args:
            filter: dict or list of dict query/queries which the elements have to match.
            limit: max number of documents to return.
            skip: number of documents to skip first.
            sort: sort field
            order: sort order
            user: request user
            permission: AccessControlPermission
            *args:
            **kwargs:

        Returns:
            The `FrameworkQueryBuilder` query pipeline with the parameter contents.
        """
        self.clear()
        self.query = Pipeline([])

        if isinstance(filter, dict):
            self.query.append(self.match_(filter))
        elif isinstance(filter, list):
            for pipe in filter:
                self.query.append(pipe)

        if user and permission:
            self.query += (AccessControlQueryBuilder().build(
                group_id=user.group_id, permission=permission))

        if limit == 0:
            results_query = [self.skip_(limit)]
        else:
            results_query = [self.skip_(skip), self.limit_(limit)]

        # TODO: Remove nasty quick hack
        if sort.startswith('fields'):
            sort_value = sort[7:]
            self.query.append({
                '$addFields': {
                    'order': {
                        '$filter': {
                            'input': '$fields',
                            'as': 'fields',
                            'cond': {
                                '$eq': ['$$fields.name', sort_value]
                            }
                        }
                    }
                }
            })
            self.query.append({'$sort': {'order': order}})
        else:
            self.query.append(self.sort_(sort=sort, order=order))

        self.query.append(
            self.facet_({
                'meta': [self.count_('total')],
                'results': results_query
            }))
        return self.query