Permalink
Fetching contributors…
Cannot retrieve contributors at this time
337 lines (206 sloc) 8.65 KB

SearchQuery API

The SearchQuery class acts as an intermediary between SearchQuerySet's abstraction and SearchBackend's actual search. Given the metadata provided by SearchQuerySet, SearchQuery builds the actual query and interacts with the SearchBackend on SearchQuerySet's behalf.

This class must be at least partially implemented on a per-backend basis, as portions are highly specific to the backend. It usually is bundled with the accompanying SearchBackend.

Most people will NOT have to use this class directly. SearchQuerySet handles all interactions with SearchQuery objects and provides a nicer interface to work with.

Should you need advanced/custom behavior, you can supply your version of SearchQuery that overrides/extends the class in the manner you see fit. You can either hook it up in a BaseEngine subclass or SearchQuerySet objects take a kwarg parameter query where you can pass in your class.

SQ Objects

For expressing more complex queries, especially involving AND/OR/NOT in different combinations, you should use SQ objects. Like django.db.models.Q objects, SQ objects can be passed to SearchQuerySet.filter and use the familiar unary operators (&, | and ~) to generate complex parts of the query.

Warning

Any data you pass to SQ objects is passed along unescaped. If you don't trust the data you're passing along, you should use the clean method on your SearchQuery to sanitize the data.

Example:

from haystack.query import SQ

# We want "title: Foo AND (tags:bar OR tags:moof)"
sqs = SearchQuerySet().filter(title='Foo').filter(SQ(tags='bar') | SQ(tags='moof'))

# To clean user-provided data:
sqs = SearchQuerySet()
clean_query = sqs.query.clean(user_query)
sqs = sqs.filter(SQ(title=clean_query) | SQ(tags=clean_query))

Internally, the SearchQuery object maintains a tree of SQ objects. Each SQ object supports what field it looks up against, what kind of lookup (i.e. the __ filters), what value it's looking for, if it's a AND/OR/NOT and tracks any children it may have. The SearchQuery.build_query method starts with the root of the tree, building part of the final query at each node until the full final query is ready for the SearchBackend.

Backend-Specific Methods

When implementing a new backend, the following methods will need to be created:

build_query_fragment

.. method:: SearchQuery.build_query_fragment(self, field, filter_type, value)

Generates a query fragment from a field, filter type and a value.

Must be implemented in backends as this will be highly backend specific.

Inheritable Methods

The following methods have a complete implementation in the base class and can largely be used unchanged.

build_query

.. method:: SearchQuery.build_query(self)

Interprets the collected query metadata and builds the final query to be sent to the backend.

build_params

.. method:: SearchQuery.build_params(self, spelling_query=None)

Generates a list of params to use when searching.

clean

.. method:: SearchQuery.clean(self, query_fragment)

Provides a mechanism for sanitizing user input before presenting the value to the backend.

A basic (override-able) implementation is provided.

run

.. method:: SearchQuery.run(self, spelling_query=None, **kwargs)

Builds and executes the query. Returns a list of search results.

Optionally passes along an alternate query for spelling suggestions.

Optionally passes along more kwargs for controlling the search query.

run_mlt

.. method:: SearchQuery.run_mlt(self, **kwargs)

Executes the More Like This. Returns a list of search results similar to the provided document (and optionally query).

run_raw

.. method:: SearchQuery.run_raw(self, **kwargs)

Executes a raw query. Returns a list of search results.

get_count

.. method:: SearchQuery.get_count(self)

Returns the number of results the backend found for the query.

If the query has not been run, this will execute the query and store the results.

get_results

.. method:: SearchQuery.get_results(self, **kwargs)

Returns the results received from the backend.

If the query has not been run, this will execute the query and store the results.

get_facet_counts

.. method:: SearchQuery.get_facet_counts(self)

Returns the results received from the backend.

If the query has not been run, this will execute the query and store the results.

boost_fragment

.. method:: SearchQuery.boost_fragment(self, boost_word, boost_value)

Generates query fragment for boosting a single word/value pair.

matching_all_fragment

.. method:: SearchQuery.matching_all_fragment(self)

Generates the query that matches all documents.

add_filter

.. method:: SearchQuery.add_filter(self, expression, value, use_not=False, use_or=False)

Narrows the search by requiring certain conditions.

add_order_by

.. method:: SearchQuery.add_order_by(self, field)

Orders the search result by a field.

clear_order_by

.. method:: SearchQuery.clear_order_by(self)

Clears out all ordering that has been already added, reverting the query to relevancy.

add_model

.. method:: SearchQuery.add_model(self, model)

Restricts the query requiring matches in the given model.

This builds upon previous additions, so you can limit to multiple models by chaining this method several times.

set_limits

.. method:: SearchQuery.set_limits(self, low=None, high=None)

Restricts the query by altering either the start, end or both offsets.

clear_limits

.. method:: SearchQuery.clear_limits(self)

Clears any existing limits.

add_boost

.. method:: SearchQuery.add_boost(self, term, boost_value)

Adds a boosted term and the amount to boost it to the query.

raw_search

.. method:: SearchQuery.raw_search(self, query_string, **kwargs)

Runs a raw query (no parsing) against the backend.

This method causes the SearchQuery to ignore the standard query-generating facilities, running only what was provided instead.

Note that any kwargs passed along will override anything provided to the rest of the SearchQuerySet.

more_like_this

.. method:: SearchQuery.more_like_this(self, model_instance)

Allows backends with support for "More Like This" to return results similar to the provided instance.

add_stats_query

.. method:: SearchQuery.add_stats_query(self,stats_field,stats_facets)

Adds stats and stats_facets queries for the Solr backend.

add_highlight

.. method:: SearchQuery.add_highlight(self)

Adds highlighting to the search results.

add_within

.. method:: SearchQuery.add_within(self, field, point_1, point_2):

Adds bounding box parameters to search query.

add_dwithin

.. method:: SearchQuery.add_dwithin(self, field, point, distance):

Adds radius-based parameters to search query.

add_distance

.. method:: SearchQuery.add_distance(self, field, point):

Denotes that results should include distance measurements from the point passed in.

add_field_facet

.. method:: SearchQuery.add_field_facet(self, field, **options)

Adds a regular facet on a field.

add_date_facet

.. method:: SearchQuery.add_date_facet(self, field, start_date, end_date, gap_by, gap_amount)

Adds a date-based facet on a field.

add_query_facet

.. method:: SearchQuery.add_query_facet(self, field, query)

Adds a query facet on a field.

add_narrow_query

.. method:: SearchQuery.add_narrow_query(self, query)

Narrows a search to a subset of all documents per the query.

Generally used in conjunction with faceting.

set_result_class

.. method:: SearchQuery.set_result_class(self, klass)

Sets the result class to use for results.

Overrides any previous usages. If None is provided, Haystack will revert back to the default SearchResult object.

using

.. method:: SearchQuery.using(self, using=None)

Allows for overriding which connection should be used. This disables the use of routers when performing the query.

If None is provided, it has no effect on what backend is used.