def get_agenda_query(query, events_only=False): if events_only: return query_string(query) else: return { 'or': [ query_string(query), nested_query( 'planning_items', planning_items_query_string(query), name='query' ) ] }
def _filter_terms(filters, events_only=False): must_term_filters = [] must_not_term_filters = [] for key, val in filters.items(): if val and key != 'coverage' and key != 'coverage_status': if key in {'service', 'urgency', 'subject', 'place'} and not events_only: must_term_filters.append({ 'or': [ {'terms': {get_aggregation_field(key): val}}, nested_query( 'planning_items', { 'bool': { 'must': [ {'terms': {'planning_items.{}'.format(get_aggregation_field(key)): val}} ] } }, name=key ) ] }) else: must_term_filters.append({'terms': {get_aggregation_field(key): val}}) if val and key == 'coverage' and not events_only: must_term_filters.append( {"nested": { "path": "coverages", "query": {"bool": {"must": [{'terms': {get_aggregation_field(key): val}}]}} }}) if val and key == 'coverage_status' and not events_only: if val == ['planned']: must_term_filters.append( {"nested": { "path": "coverages", "query": {"bool": {"must": [{'terms': {'coverages.coverage_status': ['coverage intended']}}]}} }}) else: must_not_term_filters.append( {"nested": { "path": "coverages", "query": {"bool": { "should": [ {'terms': {'coverages.coverage_status': ['coverage intended']}} ]}} }}) return {"must_term_filters": must_term_filters, "must_not_term_filters": must_not_term_filters}
def featured(self, req, lookup, featured): """Return featured items.""" user = get_user() company = get_user_company(user) if is_events_only_access(user, company): abort(403) if not featured or not featured.get('items'): return ListCursor([]) query = _agenda_query() get_resource_service('section_filters').apply_section_filter(query, self.section) planning_items_query = nested_query( 'planning_items', { 'bool': {'must': [{'terms': {'planning_items.guid': featured['items']}}]} }, name='featured' ) if req.args.get('q'): query['bool']['must'].append(query_string(req.args['q'])) planning_items_query['nested']['query']['bool']['must'].append(planning_items_query_string(req.args['q'])) query['bool']['must'].append(planning_items_query) source = {'query': query} set_post_filter(source, req) source['size'] = len(featured['items']) source['from'] = req.args.get('from', 0, type=int) if not source['from']: source['aggs'] = aggregations if company and not is_admin(user) and company.get('events_only', False): # no adhoc planning items and remove planning items and coverages fields query['bool']['must'].append({'exists': {'field': 'event'}}) _remove_fields(source, PLANNING_ITEMS_FIELDS) internal_req = ParsedRequest() internal_req.args = {'source': json.dumps(source)} cursor = super().get(internal_req, lookup) docs_by_id = {} for doc in cursor.docs: for p in (doc.get('planning_items') or []): docs_by_id[p.get('guid')] = doc # make the items display on the featured day, # it's used in ui instead of dates.start and dates.end doc.update({ '_display_from': featured['display_from'], '_display_to': featured['display_to'], }) docs = [] agenda_ids = set() for _id in featured['items']: if docs_by_id.get(_id) and docs_by_id.get(_id).get('_id') not in agenda_ids: docs.append(docs_by_id.get(_id)) agenda_ids.add(docs_by_id.get(_id).get('_id')) cursor.docs = docs return cursor
def get(self, req, lookup): if req.args.get('featured'): return self.get_featured_stories(req, lookup) query = _agenda_query() user = get_user() company = get_user_company(user) is_events_only = is_events_only_access(user, company) or req.args.get('eventsOnlyView') get_resource_service('section_filters').apply_section_filter(query, self.section) product_query = {'bool': {'must': [], 'should': []}} set_product_query( product_query, company, self.section, navigation_id=req.args.get('navigation'), events_only=is_events_only ) query['bool']['must'].append(product_query) if req.args.get('q'): test_query = {'or': []} try: q = json.loads(req.args.get('q')) if isinstance(q, dict): # used for product testing if q.get('query'): test_query['or'].append(query_string(q.get('query'))) if q.get('planning_item_query'): test_query['or'].append( nested_query( 'planning_items', planning_items_query_string(q.get('planning_item_query')), name='product_test' ) ) if test_query['or']: query['bool']['must'].append(test_query) except Exception: pass if not test_query.get('or'): query['bool']['must'].append(get_agenda_query(req.args['q'], is_events_only)) if req.args.get('id'): query['bool']['must'].append({'term': {'_id': req.args['id']}}) if req.args.get('bookmarks'): set_saved_items_query(query, req.args['bookmarks']) if req.args.get('date_from') or req.args.get('date_to'): query['bool']['should'].extend(_event_date_range(req.args)) if not is_events_only: query['bool']['should'].append(_display_date_range(req.args)) source = {'query': query} source['sort'] = [{'dates.start': 'asc'}] source['size'] = 100 # we should fetch all items for given date source['from'] = req.args.get('from', 0, type=int) set_post_filter(source, req, is_events_only) if source['from'] >= 1000: # https://www.elastic.co/guide/en/elasticsearch/guide/current/pagination.html#pagination return abort(400) if not source['from'] and not req.args.get('bookmarks'): # avoid aggregations when handling pagination source['aggs'] = get_agenda_aggregations(is_events_only) if not is_admin_or_internal(user): _remove_fields(source, PRIVATE_FIELDS) if is_events_only: # no adhoc planning items and remove planning items and coverages fields query['bool']['must'].append({'exists': {'field': 'event_id'}}) _remove_fields(source, PLANNING_ITEMS_FIELDS) internal_req = ParsedRequest() internal_req.args = {'source': json.dumps(source)} cursor = super().get(internal_req, lookup) if req.args.get('date_from') and req.args.get('date_to'): date_range = _get_date_filters(req.args) for doc in cursor.docs: # make the items display on the featured day, # it's used in ui instead of dates.start and dates.end doc.update({ '_display_from': date_range.get('gt'), '_display_to': date_range.get('lt'), }) return cursor