Example #1
0
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'
                )
            ]
        }
Example #2
0
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}
Example #3
0
    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
Example #4
0
    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