def search(request): metrics = request.find_service(IMetricsService, context=None) q = request.params.get("q", "") q = q.replace("'", '"') if q: bool_query = gather_es_queries(q) query = request.es.query(bool_query) query = query.suggest("name_suggestion", q, term={"field": "name"}) else: query = request.es.query() if request.params.get("o"): sort_key = request.params["o"] if sort_key.startswith("-"): sort = {sort_key[1:]: {"order": "desc", "unmapped_type": "long"}} else: sort = {sort_key: {"unmapped_type": "long"}} query = query.sort(sort) # Require match to all specified classifiers for classifier in request.params.getall("c"): query = query.filter("terms", classifiers=[classifier]) try: page_num = int(request.params.get("page", 1)) except ValueError: raise HTTPBadRequest("'page' must be an integer.") try: page = ElasticsearchPage(query, page=page_num, url_maker=paginate_url_factory(request)) except elasticsearch.TransportError: metrics.increment("warehouse.views.search.error") raise HTTPServiceUnavailable if page.page_count and page_num > page.page_count: raise HTTPNotFound available_filters = collections.defaultdict(list) classifiers_q = (request.db.query(Classifier).with_entities( Classifier.classifier).filter(Classifier.deprecated.is_(False)).filter( exists([release_classifiers.c.trove_id]).where( release_classifiers.c.trove_id == Classifier.id)).order_by( Classifier.classifier)) for cls in classifiers_q: first, *_ = cls.classifier.split(" :: ") available_filters[first].append(cls.classifier) def filter_key(item): try: return 0, SEARCH_FILTER_ORDER.index(item[0]), item[0] except ValueError: return 1, 0, item[0] metrics = request.find_service(IMetricsService, context=None) metrics.histogram("warehouse.views.search.results", page.item_count) return { "page": page, "term": q, "order": request.params.get("o", ""), "available_filters": sorted(available_filters.items(), key=filter_key), "applied_filters": request.params.getall("c"), }
def search(request): q = request.params.get("q", '') if q: should = [] for field in SEARCH_FIELDS: kw = {"query": q} if field in SEARCH_BOOSTS: kw["boost"] = SEARCH_BOOSTS[field] should.append(Q("match", **{field: kw})) # Add a prefix query if ``q`` is longer than one character. if len(q) > 1: should.append(Q('prefix', normalized_name=q)) query = request.es.query("dis_max", queries=should) query = query.suggest("name_suggestion", q, term={"field": "name"}) else: query = request.es.query() if request.params.get("o"): query = query.sort(request.params["o"]) if request.params.getall("c"): query = query.filter("terms", classifiers=request.params.getall("c")) try: page_num = int(request.params.get("page", 1)) except ValueError: raise HTTPBadRequest("'page' must be an integer.") page = ElasticsearchPage( query, page=page_num, url_maker=paginate_url_factory(request), ) if page.page_count and page_num > page.page_count: return HTTPNotFound() available_filters = collections.defaultdict(list) classifiers_q = (request.db.query(Classifier).with_entities( Classifier.classifier).filter( exists([release_classifiers.c.trove_id]).where( release_classifiers.c.trove_id == Classifier.id)).order_by( Classifier.classifier)) for cls in classifiers_q: first, *_ = cls.classifier.split(' :: ') available_filters[first].append(cls.classifier) def filter_key(item): try: return 0, SEARCH_FILTER_ORDER.index(item[0]), item[0] except ValueError: return 1, 0, item[0] return { "page": page, "term": q, "order": request.params.get("o", ''), "available_filters": sorted(available_filters.items(), key=filter_key), "applied_filters": request.params.getall("c"), }
def search(request): metrics = request.find_service(IMetricsService, context=None) q = request.params.get("q", "") q = q.replace("'", '"') if q: bool_query = gather_es_queries(q) query = request.es.query(bool_query) query = query.suggest("name_suggestion", q, term={"field": "name"}) else: query = request.es.query() if request.params.get("o"): sort_key = request.params["o"] if sort_key.startswith("-"): sort = {sort_key[1:]: {"order": "desc", "unmapped_type": "long"}} else: sort = {sort_key: {"unmapped_type": "long"}} query = query.sort(sort) # Require match to all specified classifiers for classifier in request.params.getall("c"): query = query.query("prefix", classifiers=classifier) try: page_num = int(request.params.get("page", 1)) except ValueError: raise HTTPBadRequest("'page' must be an integer.") try: page = ElasticsearchPage(query, page=page_num, url_maker=paginate_url_factory(request)) except elasticsearch.TransportError: metrics.increment("warehouse.views.search.error") raise HTTPServiceUnavailable if page.page_count and page_num > page.page_count: raise HTTPNotFound available_filters = collections.defaultdict(list) classifiers_q = (request.db.query(Classifier).with_entities( Classifier.classifier).filter(Classifier.deprecated.is_(False)).filter( exists([release_classifiers.c.trove_id]).where( release_classifiers.c.trove_id == Classifier.id)).order_by( Classifier.classifier)) for cls in classifiers_q: first, *_ = cls.classifier.split(" :: ") available_filters[first].append(cls.classifier) def filter_key(item): try: return 0, SEARCH_FILTER_ORDER.index(item[0]), item[0] except ValueError: return 1, 0, item[0] def form_filters_tree(split_list): """ Takes a list of lists, each of them containing a filter and one of its children. Returns a dictionary, each key being a filter and each value being the filter's children. """ d = {} for l in split_list: current_level = d for part in l: if part not in current_level: current_level[part] = {} current_level = current_level[part] return d def process_available_filters(): """ Processes available filters and returns a list of dictionaries. The value of a key in the dictionary represents its children """ sorted_filters = sorted(available_filters.items(), key=filter_key) output = [] for f in sorted_filters: classifier_list = f[1] split_list = [i.split(" :: ") for i in classifier_list] tree = form_filters_tree(split_list) output.append(tree) return output metrics = request.find_service(IMetricsService, context=None) metrics.histogram("warehouse.views.search.results", page.item_count) return { "page": page, "term": q, "order": request.params.get("o", ""), "available_filters": process_available_filters(), "applied_filters": request.params.getall("c"), }