def search( *, db_session: Session = Depends(get_db), skip: int = 0, limit: int = 10, q: str = None, type: List[str] = [ v.value for v in SearchTypes ], # hack for pydantic enum json generation see: https://github.com/samuelcolvin/pydantic/pull/1749 current_user: DispatchUser = Depends(get_current_user), ): """ Perform a search. """ if q: models = [get_class_by_tablename(t) for t in type] results = composite_search(db_session=db_session, query_str=q, models=models) else: results = [] # add a filter for restricted incidents if current_user.role != UserRoles.admin: results["Incident"] = [ i for i in results["Incident"] if i.visibility == Visibility.open ] return SearchResponse(**{ "query": q, "results": results }).dict(by_alias=False)
def match(*, db_session, filter_spec: List[dict], class_instance: Base): """Matches an class instance with a given search filter.""" table_name = get_table_name_by_class_instance(class_instance) model_cls = get_class_by_tablename(table_name) query = db_session.query(model_cls) query = apply_filters(query, filter_spec) return query.filter(model_cls.id == class_instance.id).one_or_none()
def search( *, db_session: Session = Depends(get_db), skip: int = 0, limit: int = 10, q: str = None, type: List[str] = [ v.value for v in SearchTypes ], # hack for pydantic enum json generation see: https://github.com/samuelcolvin/pydantic/pull/1749 current_user: DispatchUser = Depends(get_current_user), ): """ Perform a search. """ if q: models = [get_class_by_tablename(t) for t in type] results = composite_search(db_session=db_session, query_str=q, models=models) else: results = [] # add a filter for restricted incidents if current_user.role != UserRoles.admin: filtered_results = [] for r in results: if r["type"].lower() == "incident": if r["content"].visibility != Visibility.open: continue filtered_results.append(r) results = filtered_results return {"query": q, "results": results}
def search(*, query_str: str, query: Query, model: str, sort=False): """Perform a search based on the query.""" search_model = get_class_by_tablename(model) if not query_str.strip(): return query vector = search_model.search_vector query = query.filter(vector.op("@@")(func.tsq_parse(query_str))) if sort: query = query.order_by( desc(func.ts_rank_cd(vector, func.tsq_parse(query_str)))) return query.params(term=query_str)
def get_tag_recommendations(*, db_session: Session = Depends(get_db), model_name: str, id: int): """ Retrieves a tag recommendation based on the model and model id. """ model_object = get_class_by_tablename(model_name) model = db_session.query(model_object).filter( model_object.id == id).one_or_none() if not model: raise HTTPException( status_code=404, detail=f"No model found. ModelName: {model_name} Id: {id}") tags = get_recommendations(db_session, [t.id for t in model.tags], model_name) return {"items": tags, "total": len(tags)}
def search( *, db_session: Session = Depends(get_db), skip: int = 0, limit: int = 10, q: str = None, type: List[SearchTypes] = SearchTypes, ): """ Perform a search. """ if q: models = [get_class_by_tablename(t.name) for t in type] results = composite_search(db_session=db_session, query_str=q, models=models) else: results = [] return {"query": q, "results": results}
def search( *, db_session: Session = Depends(get_db), skip: int = 0, limit: int = 10, q: str = None, type: List[str] = [ v.value for v in SearchTypes ], # hack for pydantic enum json generation see: https://github.com/samuelcolvin/pydantic/pull/1749 ): """ Perform a search. """ if q: models = [get_class_by_tablename(t.name) for t in type] results = composite_search(db_session=db_session, query_str=q, models=models) else: results = [] return {"query": q, "results": results}
def search_filter_sort_paginate( db_session, model, query_str: str = None, page: int = 1, items_per_page: int = 5, sort_by: List[str] = None, descending: List[bool] = None, fields: List[str] = None, ops: List[str] = None, values: List[str] = None, current_user: DispatchUser = None, role: UserRoles = UserRoles.CUSTOMER, ): """Common functionality for searching, filtering, sorting, and pagination.""" model_cls = get_class_by_tablename(model) try: query = db_session.query(model_cls) if query_str: sort = False if sort_by else True query = search(query_str=query_str, query=query, model=model, sort=sort) query = apply_model_specific_filters(model_cls, query, current_user, role) filter_spec = create_filter_spec(model, fields, ops, values) query = apply_filters(query, filter_spec) if sort_by: sort_spec = create_sort_spec(model, sort_by, descending) query = apply_sort(query, sort_spec) except FieldNotFound as e: raise ValidationError( [ ErrorWrapper(FieldNotFoundError(msg=str(e)), loc="filter"), ], model=BaseModel, ) except BadFilterFormat as e: raise ValidationError( [ErrorWrapper(InvalidFilterError(msg=str(e)), loc="filter")], model=BaseModel) if items_per_page == -1: items_per_page = None # sometimes we get bad input for the search function # TODO investigate moving to a different way to parsing queries that won't through errors # e.g. websearch_to_tsquery # https://www.postgresql.org/docs/current/textsearch-controls.html try: query, pagination = apply_pagination(query, page_number=page, page_size=items_per_page) except sqlalchemy.exc.ProgrammingError as e: log.debug(e) return { "items": [], "itemsPerPage": items_per_page, "page": page, "total": 0, } return { "items": query.all(), "itemsPerPage": pagination.page_size, "page": pagination.page_number, "total": pagination.total_results, }
def get_all(*, db_session, model): """Fetches a query object based on the model class name.""" return db_session.query(get_class_by_tablename(model))
def match(*, db_session, filter_spec, model, model_id: int): """Matches an incident with a given search filter.""" model_cls = get_class_by_tablename(model) query = db_session.query(model_cls) query = apply_filters(query, filter_spec) return query.filter(model.id == model_id).one_or_none()