def VideohubChannel(included_ids=None, excluded_ids=None): f = MatchAll() if included_ids: f &= Nested(path="videohub_ref", filter=Terms(**{"videohub_ref.channel_id": included_ids})) if excluded_ids: f &= ~Nested(path="videohub_ref", filter=Terms(**{"videohub_ref.channel_id": excluded_ids}))
def Authors(usernames): # noqa included, excluded = _parse_slugs(usernames) f = MatchAll() if included: f &= Terms(**{"authors.username": included}) if excluded: f &= Terms(**{"authors.username": excluded}) return f
def Tags(slugs): # noqa included, excluded = _parse_slugs(slugs) f = MatchAll() if included: f &= Nested(path="tags", filter=Terms(**{"tags.slug": included})) if excluded: f &= ~Nested(path="tags", filter=Terms(**{"tags.slug": excluded})) return f
def FeatureTypes(slugs): # noqa included, excluded = _parse_slugs(slugs) f = MatchAll() if included: f &= Nested(path="feature_type", filter=Terms(**{"feature_type.slug": included})) if excluded: f &= ~Nested(path="feature_type", filter=Terms(**{"feature_type.slug": excluded})) return f
def preview_filter_from_query(query, id_field="id", field_map={}): """This filter includes the "excluded_ids" so they still show up in the editor.""" f = groups_filter_from_query(query, field_map=field_map) # NOTE: we don't exclude the excluded ids here so they show up in the editor # include these, please included_ids = query.get("included_ids") if included_ids: if f: f |= Terms(pk=included_ids) else: f = Terms(pk=included_ids) return f
def groups_filter_from_query(query, field_map={}): """Creates an F object for the groups of a search query.""" f = None # filter groups for group in query.get("groups", []): group_f = MatchAll() for condition in group.get("conditions", []): field_name = condition["field"] field_name = field_map.get(field_name, field_name) operation = condition["type"] values = condition["values"] if values: values = [v["value"] for v in values] if operation == "all": # NOTE: is there a better way to express this? for value in values: if "." in field_name: path = field_name.split(".")[0] group_f &= Nested( path=path, filter=Term(**{field_name: value})) else: group_f &= Term(**{field_name: value}) elif operation == "any": if "." in field_name: path = field_name.split(".")[0] group_f &= Nested(path=path, filter=Terms(**{field_name: values})) else: group_f &= Terms(**{field_name: values}) elif operation == "none": if "." in field_name: path = field_name.split(".")[0] group_f &= ~Nested( path=path, filter=Terms(**{field_name: values})) else: group_f &= ~Terms(**{field_name: values}) date_range = group.get("time") if date_range: group_f &= date_range_filter(date_range) if f: f |= group_f else: f = group_f return f
def TagBoost(slugs, boost_mode="multiply", weight=5): included, excluded = _parse_slugs(slugs) return FunctionScore(boost_mode=boost_mode, functions=[{ "filter": Nested(path="tags", filter=Terms(**{"tags.slug": included})), "weight": weight }])
def get_condition_filter(condition, field_map={}): """ Return the appropriate filter for a given group condition. # TODO: integrate this into groups_filter_from_query function. """ field_name = condition.get("field") field_name = field_map.get(field_name, field_name) operation = condition["type"] values = condition["values"] condition_filter = MatchAll() if values: values = [v["value"] for v in values] if operation == "all": for value in values: if "." in field_name: path = field_name.split(".")[0] condition_filter &= Nested( path=path, filter=Term(**{field_name: value})) else: condition_filter &= Term(**{field_name: value}) elif operation == "any": if "." in field_name: path = field_name.split(".")[0] condition_filter &= Nested( path=path, filter=Terms(**{field_name: values})) else: condition_filter &= Terms(**{field_name: values}) elif operation == "none": if "." in field_name: path = field_name.split(".")[0] condition_filter &= ~Nested( path=path, filter=Terms(**{field_name: values})) else: condition_filter &= ~Terms(**{field_name: values}) else: raise ValueError( """ES conditions must be one of the following values: ['all', 'any', 'none']""" ) return condition_filter
def filter_from_query(query, id_field="id", field_map={}): """This returns a filter which actually filters out everything, unlike the preview filter which includes excluded_ids for UI purposes. """ f = groups_filter_from_query(query, field_map=field_map) excluded_ids = query.get("excluded_ids") included_ids = query.get("included_ids") if included_ids: # include these, please if f is None: f = Terms(pk=included_ids) else: f |= Terms(pk=included_ids) if excluded_ids: # exclude these if f is None: f = MatchAll() f &= ~Terms(pk=excluded_ids) return f
def custom_search_model(model, query, preview=False, published=False, id_field="id", sort_pinned=True, field_map={}): """Filter a model with the given filter. `field_map` translates incoming field names to the appropriate ES names. """ if preview: func = preview_filter_from_query else: func = filter_from_query f = func(query, id_field=id_field, field_map=field_map) # filter by published if published: if f: f &= Range(published={"lte": timezone.now()}) else: f = Range(published={"lte": timezone.now()}) qs = model.search_objects.search(published=False) if f: qs = qs.filter(f) # possibly include a text query if query.get("query"): qs = qs.query("match", _all=query["query"]) # set up pinned ids pinned_ids = query.get("pinned_ids") if pinned_ids and sort_pinned: pinned_query = es_query.FunctionScore(boost_mode="multiply", functions=[{ "filter": Terms(id=pinned_ids), "weight": 2 }]) qs = qs.query(pinned_query) qs = qs.sort("_score", "-published") else: qs = qs.sort("-published") return qs