# HG changeset patch # User Thierry Florac # Date 1610381024 -3600 # Node ID 17aaf1ec3390d6bc966d47aa0c303b170ba818f1 # Parent 812bfc53bf5c3bf9d5c2d8ff2abfa06046e5d949 Added aggregations support to views diff -r 812bfc53bf5c -r 17aaf1ec3390 src/pyams_content_es/shared/view/__init__.py --- a/src/pyams_content_es/shared/view/__init__.py Mon Jan 11 16:48:43 2021 +0100 +++ b/src/pyams_content_es/shared/view/__init__.py Mon Jan 11 17:03:44 2021 +0100 @@ -14,15 +14,15 @@ from datetime import datetime -from elasticsearch_dsl import Q, Search +from elasticsearch_dsl import A, Q, Search from pyramid.threadlocal import get_current_registry from pyramid_es import get_client from pyams_catalog.query import CatalogResultSet from pyams_content.features.search import ISearchFolder from pyams_content.shared.common import IGNORED_CONTENT_TYPES -from pyams_content.shared.view.interfaces import IViewQuery, \ - IViewQueryEsParamsExtension, IViewQueryFilterExtension, IViewUserQuery, IWfView, RELEVANCE_ORDER +from pyams_content.shared.view.interfaces import IViewQuery, IViewQueryEsParamsExtension, \ + IViewQueryFilterExtension, IViewUserQuery, IWfView, RELEVANCE_ORDER from pyams_content.shared.view.portlet import SEARCH_EXCLUDED_ITEMS from pyams_sequence.interfaces import ISequentialIntIds from pyams_utils.adapter import ContextAdapter, adapter_config @@ -63,7 +63,8 @@ if content_path is not None: params &= Q('term', **{'parent_ids': content_path}) # check content types - params &= Q('bool', must_not=Q('terms', **{'content_type': tuple(IGNORED_CONTENT_TYPES.keys())})) + params &= Q('bool', + must_not=Q('terms', **{'content_type': tuple(IGNORED_CONTENT_TYPES.keys())})) content_types = view.get_content_types(context) if content_types: params &= Q('terms', **{'content_type': content_types}) @@ -73,7 +74,9 @@ params &= Q('terms', **{'data_type': data_types}) return params - def get_results(self, context, sort_index, reverse, limit, request=None): + def get_results(self, context, sort_index, reverse, limit, + request=None, aggregates=None): + aggregations = {} registry = request.registry client = get_client(request) params = self.get_params(context, request) @@ -85,6 +88,9 @@ .params(request_timeout=30) \ .query(params) \ .source(['internal_id']) + if aggregates: + for agg in aggregates: + search.aggs.bucket(agg['name'], A(agg['type'], **agg['params'])) # Define sort order sort_values = [] if (not sort_index) or (sort_index == RELEVANCE_ORDER): @@ -108,12 +114,15 @@ else: search = search[:999] # Get query results - items = CatalogResultSet([result.internal_id for result in search]) - total_count = search.count() - for name, adapter in sorted(registry.getAdapters((self.context,), IViewQueryFilterExtension), + results = search.execute() + items = CatalogResultSet([result.internal_id for result in results.hits]) + aggregations = results.aggregations + total_count = results.hits.total + for name, adapter in sorted(registry.getAdapters((self.context,), + IViewQueryFilterExtension), key=lambda x: x[1].weight): items = adapter.filter(context, items, request) - return unique_iter(items), total_count + return unique_iter(items), total_count, aggregations # @@ -171,3 +180,14 @@ 'header.*^3.0' ]}) | \ Q('simple_query_string', **{'query': fulltext}) + + +@adapter_config(name='content_type', context=EsSearchFolderQuery, provides=IViewUserQuery) +class EsSearchFolderContentTypeQuery(ContextAdapter): + """Search folder content-type query""" + + @staticmethod + def get_user_params(request): + content_type = request.params.get('content_type') + if content_type: + yield Q('term', **{'content_type': content_type})