def build_query_fragment(self, field, filter_type, value):
        from haystack import connections

        query_frag = ""

        if not hasattr(value, "input_type_name"):
            # Handle when we've got a ``ValuesListQuerySet``...
            if hasattr(value, "values_list"):
                value = list(value)

            if filter_type in ["regex", "iregex"]:
                value = RegExp(value)
            elif filter_type in ["fuzzy"]:
                value = PythonData(value)
            elif self.is_function(value):
                value = Exact(value)
            elif isinstance(value, six.string_types):
                # It's not an ``InputType``. Assume ``Clean``.
                value = Clean(value)
            else:
                value = PythonData(value)

        # Prepare the query using the InputType.
        prepared_value = value.prepare(self)

        if not isinstance(prepared_value, (set, list, tuple)):
            # Then convert whatever we get back to what pysolr wants if needed.
            prepared_value = self.backend.conn._from_python(prepared_value)

        if isinstance(prepared_value, str):
            words_in_value = len(prepared_value.split())
            words_in_value = 0 if words_in_value == 1 else 1

        # 'content' is a special reserved word, much like 'pk' in
        # Django's ORM layer. It indicates 'no special field'.
        if field == "content":
            index_fieldname = ""
        else:
            index_fieldname = "%s" % connections[self._using].get_unified_index().get_index_fieldname(field)

        filter_types = {
            "content": ["%s", '"%s"'],
            "contains": ["*%s*", '"*%s*"'],
            "endswith": ["*%s"],
            "startswith": ["%s*"],
            "exact": ["%s", '"%s"'],
            "gt": ["{%s TO *}"],
            "gte": ["[%s TO *]"],
            "lt": ["{* TO %s}"],
            "lte": ["[* TO %s]"],
            "fuzzy": ["%s~", '"%s"~'],
            "regex": ["/%s/"],
            "iregex": ["/%s/"],
            "isnull": ["-%s:[* TO *]", "%s:[* TO *]"],
        }

        if value.post_process is False:
            query_frag = prepared_value
        else:
            if filter_type in ["content", "exact", "contains", "startswith", "endswith", "fuzzy", "regex", "iregex",
                               "isnull"]:
                if value.input_type_name == "exact":
                    query_frag = prepared_value
                elif filter_type == "fuzzy":
                    # Check if we are using phrases (words between ")
                    # match = re.compile('^([^\\\~]*)\\\~?(\d*)?$').match(prepared_value)
                    match = re.compile("^([^\~]*)\~?(\d*)?$").match(prepared_value)
                    if match:
                        # If the user provided the ~[\d] part of the fuzzy
                        if match.group(2):
                            if not words_in_value:
                                query_frag = "%s~%s" % match.groups()
                            else:
                                query_frag = '"%s"~%s' % match.groups()
                    query_frag = (
                        filter_types[filter_type][words_in_value] % prepared_value
                        if not len(query_frag)
                        else query_frag
                    )
                elif filter_type in ["startswith", "endswith"]:
                    if words_in_value == 0:
                        query_frag = filter_types[filter_type][words_in_value] % prepared_value
                    else:
                        if filter_type in ["startswith"]:
                            query_frag = " AND ".join(prepared_value.split()) + "*"
                        else:
                            query_frag = "*" + " AND ".join(prepared_value.split())
                elif filter_type == "isnull":
                    if prepared_value == "true":
                        return filter_types[filter_type][0] % index_fieldname
                    elif prepared_value == "false":
                        return filter_types[filter_type][1] % index_fieldname
                else:
                    query_frag = filter_types[filter_type][words_in_value] % prepared_value
            elif filter_type == "in":
                in_options = []

                if not prepared_value:
                    query_frag = "(!*:*)"
                else:
                    for possible_value in prepared_value:
                        in_options.append('"%s"' % self.backend.conn._from_python(possible_value))

                    query_frag = "(%s)" % " OR ".join(in_options)
            elif filter_type == "range":
                start = self.backend.conn._from_python(prepared_value[0])
                end = self.backend.conn._from_python(prepared_value[1])
                query_frag = '["%s" TO "%s"]' % (start, end)
            elif filter_type == "exact":
                if value.input_type_name == "exact":
                    query_frag = prepared_value
                else:
                    prepared_value = Exact(prepared_value).prepare(self)
                    query_frag = filter_types[filter_type][words_in_value] % prepared_value
            else:
                if value.input_type_name != "exact":
                    prepared_value = Exact(prepared_value).prepare(self)

                query_frag = filter_types[filter_type][words_in_value] % prepared_value

        if len(query_frag) and not isinstance(value, Raw) and filter_type not in ["regex", "iregex"]:
            if not query_frag.startswith("(") and not query_frag.endswith(")"):
                query_frag = "(%s)" % query_frag
        elif isinstance(value, Raw):
            return query_frag

        # Check if the field is making a reference to a Tuple/UDF object

        # Obtain the list of searchable fields available at the Index
        # class associated to the model
        searchable_fields = connections[self._using].get_unified_index().all_searchfields()

        # Get the model attribute that is connected to the current
        # index search field.
        # If the param was for a dict entry, the index_fieldname won't be in the list of
        # searcheable fields, as the field is a combination of the fieldname plus the key
        if index_fieldname in searchable_fields:
            model_attr = searchable_fields[index_fieldname].model_attr

            if model_attr and "." in model_attr:
                return "{{!tuple v='{field}:{value}'}}".format(field=model_attr, value=query_frag)
            else:
                return "%s:%s" % (index_fieldname, query_frag)
        else:
            return "%s:%s" % (index_fieldname, query_frag)
    def build_query_fragment(self, field, filter_type, value):
        from haystack import connections
        query_frag = ''

        if not hasattr(value, 'input_type_name'):
            # Handle when we've got a ``ValuesListQuerySet``...
            if hasattr(value, 'values_list'):
                value = list(value)

            if isinstance(value, six.string_types):
                # It's not an ``InputType``. Assume ``Clean``.
                value = Clean(value)
            else:
                value = PythonData(value)

        # Prepare the query using the InputType.
        prepared_value = value.prepare(self)

        if not isinstance(prepared_value, (set, list, tuple)):
            # Then convert whatever we get back to what pysolr wants if needed.
            prepared_value = self.backend._from_python(prepared_value)

        # 'content' is a special reserved word, much like 'pk' in
        # Django's ORM layer. It indicates 'no special field'.
        if field == 'content':
            index_fieldname = ''
        else:
            index_fieldname = u'%s:' % connections[
                self._using].get_unified_index().get_index_fieldname(field)

        filter_types = {
            'content': u'%s',
            'contains': u'*%s*',
            'endswith': u'*%s',
            'startswith': u'%s*',
            'exact': u'%s',
            'gt': u'{%s TO *}',
            'gte': u'[%s TO *]',
            'lt': u'{* TO %s}',
            'lte': u'[* TO %s]',
            'fuzzy': u'%s~',
        }

        if value.post_process is False:
            query_frag = prepared_value
        else:
            if filter_type in [
                    'content', 'contains', 'startswith', 'endswith', 'fuzzy'
            ]:
                if value.input_type_name == 'exact':
                    query_frag = prepared_value
                else:
                    # Iterate over terms & incorportate the converted form of each into the query.
                    terms = []

                    if isinstance(prepared_value, six.string_types):
                        for possible_value in prepared_value.split(' '):
                            terms.append(
                                filter_types[filter_type] %
                                self.backend._from_python(possible_value))
                    else:
                        terms.append(filter_types[filter_type] %
                                     self.backend._from_python(prepared_value))

                    if len(terms) == 1:
                        query_frag = terms[0]
                    else:
                        query_frag = u"(%s)" % " AND ".join(terms)
            elif filter_type == 'in':
                in_options = []

                if not prepared_value:
                    query_frag = u'(!*:*)'
                else:
                    for possible_value in prepared_value:
                        in_options.append(
                            u'"%s"' %
                            self.backend._from_python(possible_value))
                    query_frag = u"(%s)" % " OR ".join(in_options)

            elif filter_type == 'range':
                start = self.backend._from_python(prepared_value[0])
                end = self.backend._from_python(prepared_value[1])
                query_frag = u'["%s" TO "%s"]' % (start, end)
            elif filter_type == 'exact':
                if value.input_type_name == 'exact':
                    query_frag = prepared_value
                else:
                    prepared_value = Exact(prepared_value).prepare(self)
                    query_frag = filter_types[filter_type] % prepared_value
            else:
                if value.input_type_name != 'exact':
                    prepared_value = Exact(prepared_value).prepare(self)

                query_frag = filter_types[filter_type] % prepared_value

        if len(query_frag) and not isinstance(value, Raw):
            if not query_frag.startswith('(') and not query_frag.endswith(')'):
                query_frag = "(%s)" % query_frag

        return u"%s%s" % (index_fieldname, query_frag)
예제 #3
0
    def build_query_fragment(self, field, filter_type, value):
        from haystack import connections
        query_frag = ''
        is_datetime = False

        if not hasattr(value, 'input_type_name'):
            # Handle when we've got a ``ValuesListQuerySet``...
            if hasattr(value, 'values_list'):
                value = list(value)

            if hasattr(value, 'strftime'):
                is_datetime = True

            if isinstance(value, basestring) and value != ' ':
                # It's not an ``InputType``. Assume ``Clean``.
                value = Clean(value)
            else:
                value = PythonData(value)

        # Prepare the query using the InputType.
        prepared_value = value.prepare(self)

        if not isinstance(prepared_value, (set, list, tuple)):
            # Then convert whatever we get back to what pysolr wants if needed.
            prepared_value = self.backend._from_python(prepared_value)

        # 'content' is a special reserved word, much like 'pk' in
        # Django's ORM layer. It indicates 'no special field'.
        if field == 'content':
            index_fieldname = ''
        else:
            index_fieldname = u'%s:' % connections[
                self._using].get_unified_index().get_index_fieldname(field)

        filter_types = {
            'contains': '%s',
            'startswith': "%s*",
            'exact': '%s',
            'gt': "{%s to}",
            'gte': "[%s to]",
            'lt': "{to %s}",
            'lte': "[to %s]",
        }

        if value.post_process is False:
            query_frag = prepared_value
        else:
            if filter_type in ['contains', 'startswith']:
                if value.input_type_name == 'exact':
                    query_frag = prepared_value
                else:
                    # Iterate over terms & incorportate the converted form of each into the query.
                    terms = []

                    if isinstance(prepared_value, basestring):
                        possible_values = prepared_value.split(' ')
                    else:
                        if is_datetime is True:
                            prepared_value = self._convert_datetime(
                                prepared_value)

                        possible_values = [prepared_value]

                    for possible_value in possible_values:
                        terms.append(filter_types[filter_type] %
                                     self.backend._from_python(possible_value))

                    if len(terms) == 1:
                        query_frag = terms[0]
                    else:
                        query_frag = u"(%s)" % " AND ".join(terms)
            elif filter_type == 'in':
                in_options = []

                for possible_value in prepared_value:
                    is_datetime = False

                    if hasattr(possible_value, 'strftime'):
                        is_datetime = True

                    pv = self.backend._from_python(possible_value)

                    if is_datetime is True:
                        pv = self._convert_datetime(pv)

                    in_options.append('"%s"' % pv)

                query_frag = "(%s)" % " OR ".join(in_options)
            elif filter_type == 'range':
                start = self.backend._from_python(prepared_value[0])
                end = self.backend._from_python(prepared_value[1])

                if hasattr(prepared_value[0], 'strftime'):
                    start = self._convert_datetime(start)

                if hasattr(prepared_value[1], 'strftime'):
                    end = self._convert_datetime(end)

                query_frag = u"[%s to %s]" % (start, end)
            elif filter_type == 'exact':
                if value.input_type_name == 'exact':
                    query_frag = prepared_value
                else:
                    prepared_value = Exact(prepared_value).prepare(self)
                    query_frag = filter_types[filter_type] % prepared_value
            else:
                if is_datetime is True:
                    prepared_value = self._convert_datetime(prepared_value)

                query_frag = filter_types[filter_type] % prepared_value

        return u"%s%s" % (index_fieldname, query_frag)
예제 #4
0
    def build_query_fragment(self, field, filter_type, value):
        from haystack import connections

        query_frag = ""
        is_datetime = False

        if not hasattr(value, "input_type_name"):
            # Handle when we've got a ``ValuesListQuerySet``...
            if hasattr(value, "values_list"):
                value = list(value)

            if hasattr(value, "strftime"):
                is_datetime = True

            if isinstance(value, str) and value != " ":
                # It's not an ``InputType``. Assume ``Clean``.
                value = Clean(value)
            else:
                value = PythonData(value)

        # Prepare the query using the InputType.
        prepared_value = value.prepare(self)

        if not isinstance(prepared_value, (set, list, tuple)):
            # Then convert whatever we get back to what pysolr wants if needed.
            prepared_value = self.backend._from_python(prepared_value)

        # 'content' is a special reserved word, much like 'pk' in
        # Django's ORM layer. It indicates 'no special field'.
        if field == "content":
            index_fieldname = ""
        else:
            index_fieldname = "%s:" % connections[
                self._using].get_unified_index().get_index_fieldname(field)

        filter_types = {
            "content": "%s",
            "contains": "*%s*",
            "endswith": "*%s",
            "startswith": "%s*",
            "exact": "%s",
            "gt": "{%s to}",
            "gte": "[%s to]",
            "lt": "{to %s}",
            "lte": "[to %s]",
            "fuzzy": "%s~{}/%d".format(FUZZY_WHOOSH_MAX_EDITS),
        }

        if value.post_process is False:
            query_frag = prepared_value
        else:
            if filter_type in [
                    "content",
                    "contains",
                    "startswith",
                    "endswith",
                    "fuzzy",
            ]:
                if value.input_type_name == "exact":
                    query_frag = prepared_value
                else:
                    # Iterate over terms & incorportate the converted form of each into the query.
                    terms = []

                    if isinstance(prepared_value, str):
                        possible_values = prepared_value.split(" ")
                    else:
                        if is_datetime is True:
                            prepared_value = self._convert_datetime(
                                prepared_value)

                        possible_values = [prepared_value]

                    for possible_value in possible_values:
                        possible_value_str = self.backend._from_python(
                            possible_value)
                        if filter_type == "fuzzy":
                            terms.append(filter_types[filter_type] % (
                                possible_value_str,
                                min(FUZZY_WHOOSH_MIN_PREFIX,
                                    len(possible_value_str)),
                            ))
                        else:
                            terms.append(filter_types[filter_type] %
                                         possible_value_str)

                    if len(terms) == 1:
                        query_frag = terms[0]
                    else:
                        query_frag = "(%s)" % " AND ".join(terms)
            elif filter_type == "in":
                in_options = []

                for possible_value in prepared_value:
                    is_datetime = False

                    if hasattr(possible_value, "strftime"):
                        is_datetime = True

                    pv = self.backend._from_python(possible_value)

                    if is_datetime is True:
                        pv = self._convert_datetime(pv)

                    if isinstance(pv, str) and not is_datetime:
                        in_options.append('"%s"' % pv)
                    else:
                        in_options.append("%s" % pv)

                query_frag = "(%s)" % " OR ".join(in_options)
            elif filter_type == "range":
                start = self.backend._from_python(prepared_value[0])
                end = self.backend._from_python(prepared_value[1])

                if hasattr(prepared_value[0], "strftime"):
                    start = self._convert_datetime(start)

                if hasattr(prepared_value[1], "strftime"):
                    end = self._convert_datetime(end)

                query_frag = "[%s to %s]" % (start, end)
            elif filter_type == "exact":
                if value.input_type_name == "exact":
                    query_frag = prepared_value
                else:
                    prepared_value = Exact(prepared_value).prepare(self)
                    query_frag = filter_types[filter_type] % prepared_value
            else:
                if is_datetime is True:
                    prepared_value = self._convert_datetime(prepared_value)

                query_frag = filter_types[filter_type] % prepared_value

        if len(query_frag) and not isinstance(value, Raw):
            if not query_frag.startswith("(") and not query_frag.endswith(")"):
                query_frag = "(%s)" % query_frag

        return "%s%s" % (index_fieldname, query_frag)
예제 #5
0
파일: views.py 프로젝트: leihuagh/coursys
def _query_results(query, person):
    """
    Actually build the query results for this person.

    Make sure any result.content_type values are reflected in RESULT_TYPE_DISPLAY for display to the user.
    """
    if len(query) < 2:
        return []

    query = query.replace(
        '@sfu.ca', '')  # hack to make email addresses searchable as userids
    query = Clean(query)

    # offerings person was a member of (coredata.CourseOffering)
    if person:
        members = Member.objects.filter(person=person).exclude(
            role='DROP').select_related('offering')
        offering_slugs = set(m.offering.slug for m in members)
        offering_results = SearchQuerySet().models(CourseOffering).filter(
            text=query)  # offerings that match the query
        offering_results = offering_results.filter(
            slug__in=offering_slugs)  # ... and this person was in
    else:
        members = []
        offering_results = []

    # pages this person can view (pages.Page)
    page_acl = set(['ALL'])
    for m in members:
        # builds a set of offering_slug+"_"+acl_value strings, which will match the permission_key field in the index
        member_acl = set("%s_%s" % (m.offering.slug, acl)
                         for acl in ACL_ROLES[m.role] if acl != 'ALL')
        page_acl |= member_acl

    page_results = SearchQuerySet().models(Page).filter(
        text=query)  # pages that match the query
    page_results = page_results.filter(
        permission_key__in=page_acl)  # ... and are visible to this user

    # discussion this person can view (discussion.DiscussionTopic)
    if person:
        discuss_results = SearchQuerySet().models(DiscussionTopic).filter(
            text=query)  # discussions that match the query
        discuss_results = discuss_results.filter(
            slug__in=offering_slugs)  # ... and this person was in
    else:
        discuss_results = []

    # students taught by instructor (coredata.Member)
    instr_members = Member.objects.filter(person=person, role__in=['INST','TA']).exclude(offering__component='CAN') \
        .select_related('offering')
    if person and instr_members:
        offering_slugs = set(m.offering.slug for m in instr_members)
        member_results = SearchQuerySet().models(Member).filter(
            text=query)  # members that match the query
        member_results = member_results.filter(
            offering_slug__in=offering_slugs
        )  # ... and this person was the instructor for
        member_results = member_results.load_all()
    else:
        member_results = []

    # combine and limit to best results
    results = itertools.chain(
        offering_results[:MAX_RESULTS],
        page_results[:MAX_RESULTS],
        member_results[:MAX_RESULTS],
        discuss_results[:MAX_RESULTS],
    )
    results = (r for r in results if r is not None)
    results = list(results)
    results.sort(key=lambda result: -result.score)
    results = results[:
                      MAX_RESULTS]  # (list before this could be n*MAX_RESULTS long)

    return results
예제 #6
0
    def get_queryset(self):
        queryset = SearchQuerySet()

        if hasattr(self.request, 'accepted_media_type') and re.match(
                KML_REGEXP, self.request.accepted_media_type):
            queryset = queryset.models(Unit)
            self.only_fields['unit'].extend(['street_address', 'www'])

        input_val = self.request.query_params.get('input', '').strip()
        q_val = self.request.query_params.get('q', '').strip()

        if not input_val and not q_val:
            raise ParseError(
                "Supply search terms with 'q=' or autocomplete entry with 'input='"
            )
        if input_val and q_val:
            raise ParseError("Supply either 'q' or 'input', not both")

        if input_val:
            queryset = queryset.filter(
                SQ(autosuggest=input_val)
                | SQ(autosuggest_extra_searchwords=input_val)
                | SQ(autosuggest_exact__exact=input_val)
                | SQ(SQ(number=input_val) & SQ(autosuggest=input_val)))
        else:
            queryset = (queryset.filter(name=Clean(q_val)).filter_or(
                text=Clean(q_val)).filter_or(
                    extra_searchwords=q_val).filter_or(address=q_val))

        IS_NOT_UNIT_SQ = (SQ(django_ct='services.service')
                          | SQ(django_ct='services.servicenode')
                          | SQ(django_ct='munigeo.address'))

        if 'municipality' in self.request.query_params:
            val = self.request.query_params['municipality'].lower().strip()
            if len(val) > 0:
                municipalities = val.split(',')

                muni_sq = SQ(municipality=municipalities.pop().strip())
                for m in municipalities:
                    muni_sq |= SQ(municipality=m)

                queryset = queryset.filter(SQ(muni_sq | IS_NOT_UNIT_SQ))

        if 'city_as_department' in self.request.query_params:
            val = self.request.query_params['city_as_department'].lower(
            ).strip()

            if len(val) > 0:
                deps_uuid = val.split(',')

                # forming municipality search query
                deps = Department.objects.filter(
                    uuid__in=deps_uuid).select_related('municipality')
                munis = [d.municipality.name for d in deps]

                muni_sq = SQ(municipality=munis.pop())
                for m in munis:
                    muni_sq |= SQ(municipality=m)

                # forming root_deparment search query
                dep_sq = SQ(root_department=deps_uuid.pop().strip())
                for d in deps_uuid:
                    dep_sq |= SQ(root_department=d)

                # updating queryset
                queryset = queryset.filter(
                    SQ(muni_sq | dep_sq | IS_NOT_UNIT_SQ))

        service = self.request.query_params.get('service')
        if service:
            services = service.split(',')
            queryset = queryset.filter(django_ct='services.unit').filter(
                services__in=services)

        # Only units marked public should be returned. For other types,
        # public is always True.
        queryset = queryset.filter(public='true')

        models = set()
        types = self.request.query_params.get('type', '').split(',')
        for t in types:
            if t == 'service_node':
                models.add(ServiceNode)
            elif t == 'service':
                models.add(Service)
            elif t == 'unit':
                models.add(Unit)
            elif t == 'address':
                models.add(Address)
            elif t == 'administrative_division':
                models.add(AdministrativeDivision)
        if self._is_kml_media_type_request():
            queryset = queryset.models(Unit)
        elif len(models) > 0:
            queryset = queryset.models(*list(models))
        else:
            # Hide the to-be-deprecated servicenode from default types
            queryset = queryset.models(Service, Unit, Address,
                                       AdministrativeDivision)
        return queryset
예제 #7
0
    def build_query_fragment(self, field, filter_type, value):
        from haystack import connections

        query_frag = ""

        if not hasattr(value, "input_type_name"):
            # Handle when we've got a ``ValuesListQuerySet``...
            if hasattr(value, "values_list"):
                value = list(value)

            if isinstance(value, six.string_types):
                # It's not an ``InputType``. Assume ``Clean``.
                value = Clean(value)
            else:
                value = PythonData(value)

        # Prepare the query using the InputType.
        prepared_value = value.prepare(self)

        if not isinstance(prepared_value, (set, list, tuple)):
            # Then convert whatever we get back to what pysolr wants if needed.
            prepared_value = self.backend.conn._from_python(prepared_value)

        # 'content' is a special reserved word, much like 'pk' in
        # Django's ORM layer. It indicates 'no special field'.
        if field == "content":
            index_fieldname = ""
        else:
            index_fieldname = "%s:" % connections[
                self._using
            ].get_unified_index().get_index_fieldname(field)

        filter_types = {
            "content": "%s",
            "contains": "*%s*",
            "endswith": "*%s",
            "startswith": "%s*",
            "exact": "%s",
            "gt": "{%s TO *}",
            "gte": "[%s TO *]",
            "lt": "{* TO %s}",
            "lte": "[* TO %s]",
            "fuzzy": "%s~",
        }

        if value.post_process is False:
            query_frag = prepared_value
        else:
            if filter_type in [
                "content",
                "contains",
                "startswith",
                "endswith",
                "fuzzy",
            ]:
                if value.input_type_name == "exact":
                    query_frag = prepared_value
                else:
                    # Iterate over terms & incorportate the converted form of each into the query.
                    terms = []

                    for possible_value in prepared_value.split(" "):
                        terms.append(
                            filter_types[filter_type]
                            % self.backend.conn._from_python(possible_value)
                        )

                    if len(terms) == 1:
                        query_frag = terms[0]
                    else:
                        query_frag = "(%s)" % " AND ".join(terms)
            elif filter_type == "in":
                in_options = []

                if not prepared_value:
                    query_frag = "(!*:*)"
                else:
                    for possible_value in prepared_value:
                        in_options.append(
                            '"%s"' % self.backend.conn._from_python(possible_value)
                        )

                    query_frag = "(%s)" % " OR ".join(in_options)
            elif filter_type == "range":
                start = self.backend.conn._from_python(prepared_value[0])
                end = self.backend.conn._from_python(prepared_value[1])
                query_frag = '["%s" TO "%s"]' % (start, end)
            elif filter_type == "exact":
                if value.input_type_name == "exact":
                    query_frag = prepared_value
                else:
                    prepared_value = Exact(prepared_value).prepare(self)
                    query_frag = filter_types[filter_type] % prepared_value
            else:
                if value.input_type_name != "exact":
                    prepared_value = Exact(prepared_value).prepare(self)

                query_frag = filter_types[filter_type] % prepared_value

        if len(query_frag) and not isinstance(value, Raw):
            if not query_frag.startswith("(") and not query_frag.endswith(")"):
                query_frag = "(%s)" % query_frag

        return "%s%s" % (index_fieldname, query_frag)
예제 #8
0
 def reduce_query(self, keywords):
     query = reduce(self.join_search_queries, keywords)
     if not isinstance(query, SQ):
         return SQ(contains=Clean(query))
     return query
예제 #9
0
 def join_search_queries(self, left, right):
     left = left if isinstance(left, SQ) else SQ(contains=Clean(left))
     right = right if isinstance(right, SQ) else SQ(contains=Clean(right))
     return left & right
예제 #10
0
def ask_search(request, language='en', as_json=False):
    if 'selected_facets' in request.GET:
        return redirect_ask_search(request, language=language)
    language_map = {
        'en': {
            'slug': 'ask-cfpb-search-results',
            'query': SearchQuerySet().models(EnglishAnswerProxy)
        },
        'es': {
            'slug': 'respuestas',
            'query': SearchQuerySet().models(SpanishAnswerProxy)
        }
    }
    _map = language_map[language]
    sqs = _map['query']
    clean_query = Clean(request.GET.get('q', ''))
    clean_qstring = clean_query.query_string.strip()
    qstring = clean_qstring
    query_sqs = sqs.filter(content=clean_query)
    results_page = get_object_or_404(AnswerResultsPage,
                                     language=language,
                                     slug=_map['slug'])

    # If there's no query string, don't search
    if not qstring:
        results_page.query = ''
        results_page.result_query = ''
        return results_page.serve(request)

    # If we have no results from our query, let's try to suggest a better one
    suggestion = sqs.spelling_suggestion(qstring)
    if suggestion == qstring:
        suggestion = None
    elif (query_sqs.count() == 0 and request.GET.get('correct', '1') == '1'
          and flag_enabled('ASK_SEARCH_TYPOS', request=request)):
        query_sqs = sqs.filter(content=suggestion)
        qstring, suggestion = suggestion, qstring

    if as_json:
        results = {
            'query':
            clean_qstring,
            'result_query':
            qstring,
            'suggestion':
            suggestion,
            'results': [{
                'question': result.autocomplete,
                'url': result.url,
                'text': result.text
            } for result in query_sqs]
        }
        json_results = json.dumps(results)
        return HttpResponse(json_results, content_type='application/json')
    else:
        results_page.query = clean_qstring
        results_page.result_query = qstring
        results_page.suggestion = suggestion
        results_page.answers = []

        for result in query_sqs:
            results_page.answers.append(
                (result.url, result.autocomplete, result.text))
        return results_page.serve(request)
예제 #11
0
    def search(self):
        if not self.is_valid():
            return self.no_query_found()

        sqs = self.searchqueryset

        for facet in self.selected_facets:
            if ":" not in facet:
                continue

            field, value = facet.split(":", 1)

            if value:
                sqs = sqs.narrow(u'%s:%s' % (field, value))

        #print(self.cleaned_data)

        if self.cleaned_data['q']:
            sqs = sqs.auto_query(self.cleaned_data['q'])

        if self.cleaned_data['title']:
            sqs = sqs.filter(title=AutoQuery(self.cleaned_data['title']))

        if self.cleaned_data['license']:
            sqs = sqs.filter(license=AutoQuery(self.cleaned_data['license']))

        if self.cleaned_data['funded_by']:
            sqs = sqs.filter(
                funded_by=AutoQuery(self.cleaned_data['funded_by']))

        if self.cleaned_data['domain']:
            sqs = sqs.filter(
                web_domains__in=AutoQuery(self.cleaned_data['domain']))

        if self.cleaned_data['exclude']:
            sqs = sqs.exclude(content=Clean(self.cleaned_data['exclude']))

        if self.cleaned_data['concept']:
            #expand concept selection as wide as we can
            m_concepts = self.cleaned_data['concept'].search_matched(
            ).alternative_children().get_descendants(include_self=True)
            sqs = sqs.filter(concepts__in=as_ids(m_concepts.distinct()))
            #TODO use keywords to search meta data (dataset's own reported keywords)?

        if self.cleaned_data['publisher']:
            #TODO expand publisher selection to include subpublishers
            m_publishers = self.cleaned_data['publisher']
            sqs = sqs.filter(publisher__in=as_ids(m_publishers))

        if self.cleaned_data['spatial_entity']:
            sqs = sqs.filter(
                spatial_entity__in=as_ids(self.cleaned_data['spatial_entity']))

        if self.cleaned_data['location_lng'] and self.cleaned_data[
                'location_lat']:
            point = Point(self.cleaned_data['location_lat'],
                          self.cleaned_data['location_lng'])
            sqs = sqs.dwithin('location', point, D(mi=2))

        if self.cleaned_data['language']:
            sqs = sqs.filter(language=self.cleaned_data['language'])

        if self.cleaned_data['access_level']:
            sqs = sqs.filter(
                access_level__in=self.cleaned_data['access_level'])

        if self.cleaned_data['sort_by']:
            sqs = sqs.order_by(self.cleaned_data['sort_by'])

        if self.cleaned_data['result_types']:
            models = map(model_choice_to_model,
                         self.cleaned_data['result_types'])
            sqs = sqs.models(*models)
        else:
            sqs = sqs.models(Story, CatalogRecord)

        return sqs
예제 #12
0
 def has_permission(self, request, view):
     q = request.QUERY_PARAMS.get('q')
     query_length = getattr(settings, "SEARCH_QUERY_LENGTH", 3)
     if not (q and len(Clean(q).query_string) > query_length):
         return False
     return True