1
0
mirror of https://github.com/django/django.git synced 2025-10-24 14:16:09 +00:00

Fixed #28041 -- Added Lexeme expression to contrib.postgres.search.

This expression automatically escapes its input and allows
fine-grained control over prefix matching and term weighting
via logical combinations.

Thanks Mariusz Felisiak, Adam Zapletal, Paolo Melchiorre,
Jacob Walls, Adam Johnson, and Simon Charette for reviews.

Co-authored-by: joetsoi <joetsoi@users.noreply.github.com>
Co-authored-by: Karl Hobley <karl@kaed.uk>
Co-authored-by: Alexandr Tatarinov <tatarinov1997@gmail.com>
This commit is contained in:
GappleBee
2017-04-06 16:42:49 +01:00
committed by Jacob Walls
parent e08fa42fa6
commit 218f69f05e
4 changed files with 423 additions and 1 deletions

View File

@@ -96,7 +96,7 @@ Examples:
.. code-block:: pycon
>>> from django.contrib.postgres.search import SearchQuery
>>> from django.contrib.postgres.search import SearchQuery, Lexeme
>>> SearchQuery("red tomato") # two keywords
>>> SearchQuery("tomato red") # same results as above
>>> SearchQuery("red tomato", search_type="phrase") # a phrase
@@ -105,6 +105,7 @@ Examples:
>>> SearchQuery(
... "'tomato' ('red' OR 'green')", search_type="websearch"
... ) # websearch operators
>>> SearchQuery(Lexeme("tomato") & (Lexeme("red") | Lexeme("green"))) # Lexeme objects
``SearchQuery`` terms can be combined logically to provide more flexibility:
@@ -118,6 +119,10 @@ Examples:
See :ref:`postgresql-fts-search-configuration` for an explanation of the
``config`` parameter.
.. versionchanged:: 6.0
:class:`Lexeme` objects were added.
``SearchRank``
==============
@@ -276,6 +281,53 @@ floats to :class:`SearchRank` as ``weights`` in the same order above:
>>> rank = SearchRank(vector, query, weights=[0.2, 0.4, 0.6, 0.8])
>>> Entry.objects.annotate(rank=rank).filter(rank__gte=0.3).order_by("-rank")
``Lexeme``
==========
.. versionadded:: 6.0
.. class:: Lexeme(value, output_field=None, *, invert=False, prefix=False, weight=None)
``Lexeme`` objects allow search operators to be safely used with strings from
an untrusted source. The content of each lexeme is escaped so that any
operators that may exist in the string itself will not be interpreted.
You can combine lexemes with other lexemes using the ``&`` and ``|`` operators
and also negate them with the ``~`` operator. For example:
.. code-block:: pycon
>>> from django.contrib.postgres.search import SearchQuery, SearchVector, Lexeme
>>> vector = SearchVector("body_text", "blog__tagline")
>>> Entry.objects.annotate(search=vector).filter(
... search=SearchQuery(Lexeme("fruit") & Lexeme("dessert"))
... )
<QuerySet [<Entry: Apple Crumble Recipes>, <Entry: Banana Split Recipes>]>
.. code-block:: pycon
>>> Entry.objects.annotate(search=vector).filter(
... search=SearchQuery(Lexeme("fruit") & Lexeme("dessert") & ~Lexeme("banana"))
... )
<QuerySet [<Entry: Apple Crumble Recipes>]>
Lexeme objects also support term weighting and prefixes:
.. code-block:: pycon
>>> Entry.objects.annotate(search=vector).filter(
... search=SearchQuery(Lexeme("Pizza") | Lexeme("Cheese"))
... )
<QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]>
>>> Entry.objects.annotate(search=vector).filter(
... search=SearchQuery(Lexeme("Pizza") | Lexeme("Cheese", weight="A"))
... )
<QuerySet [<Entry: Pizza recipes>]>
>>> Entry.objects.annotate(search=vector).filter(
... search=SearchQuery(Lexeme("za", prefix=True))
... )
<QuerySet []>
Performance
===========