# Django 6.0.7 documentation

# Fulltextsökning

Databasfunktionerna i modulen `django.contrib.postgres.search` underlättar användningen av PostgreSQLs fulltextsökmotor.

I exemplen i det här dokumentet använder vi de modeller som definieras i Göra förfrågningar.

Se även

För en översikt på hög nivå över sökning, se topic documentation.

## Uppslagsordet `search`

Ett vanligt sätt att använda fulltextsökning är att söka en enskild term mot en enskild kolumn i databasen. Till exempel:

    >>> Entry.objects.filter(body_text__search="Cheese")
    <QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]>

Detta skapar en `to_tsvector` i databasen från fältet `body_text` och en `plainto_tsquery` från söktermen `'Cheese'`, båda med standardkonfigurationen för databassökning. Resultaten erhålls genom att matcha frågan och vektorn.

För att använda `search`-uppslaget måste `'django.contrib.postgres` finnas i din `INSTALLED_APPS`.

## `SökVektor`

class SearchVector(*expressions, config=None, weight=None)

Att söka mot ett enda fält är bra men ganska begränsande. De `Entry`-instanser vi söker tillhör en `Blog`, som har ett `tagline`-fält. Om du vill söka mot båda fälten använder du en `SearchVector`:

    >>> from django.contrib.postgres.search import SearchVector
    >>> Entry.objects.annotate(
    ...     search=SearchVector("body_text", "blog__tagline"),
    ... ).filter(search="Cheese")
    <QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]>

Argumenten till `SearchVector` kan vara vilken `Expression`` som helst eller namnet på ett fält. Flera argument kommer att sammanfogas med ett mellanslag så att sökdokumentet innehåller dem alla.

`SearchVector`-objekt kan kombineras med varandra, vilket gör att du kan återanvända dem. Ett exempel:

    >>> Entry.objects.annotate(
    ...     search=SearchVector("body_text") + SearchVector("blog__tagline"),
    ... ).filter(search="Cheese")
    <QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]>

Se Ändra sökkonfigurationen och Viktning av frågor för en förklaring av parametrarna `config` och `weight`.

## `Sökfråga`

class SearchQuery(value, config=None, search_type='plain')

`SearchQuery` översätter de termer som användaren anger till ett sökfrågeobjekt som databasen jämför med en sökvektor. Som standard skickas alla ord som användaren anger genom stamningsalgoritmerna och sedan letar den efter matchningar för alla resulterande termer.

Om `search_type` är `'plain`, vilket är standard, behandlas termerna som separata nyckelord. Om `search_type` är `'phrase` behandlas termerna som en enda fras. Om `search_type` är `'raw` kan du ange en formaterad sökfråga med termer och operatorer. Om `search_type` är `'websearch` kan du ange en formaterad sökfråga som liknar den som används av webbsökmotorer. `'websearch'` kräver PostgreSQL ≥ 11. Läs PostgreSQL: s Full Text Search docs för att lära dig mer om skillnader och syntax. Exempel:

    >>> 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
    >>> SearchQuery("tomato red", search_type="phrase")  # a different phrase
    >>> SearchQuery("'tomato' & ('red' | 'green')", search_type="raw")  # boolean operators
    >>> SearchQuery(
    ...     "'tomato' ('red' OR 'green')", search_type="websearch"
    ... )  # websearch operators
    >>> SearchQuery(Lexeme("tomato") & (Lexeme("red") | Lexeme("green")))  # Lexeme objects

termerna i `SearchQuery` kan kombineras logiskt för att ge mer flexibilitet:

    >>> from django.contrib.postgres.search import SearchQuery
    >>> SearchQuery("meat") & SearchQuery("cheese")  # AND
    >>> SearchQuery("meat") | SearchQuery("cheese")  # OR
    >>> ~SearchQuery("meat")  # NOT

Se Ändra sökkonfigurationen för en förklaring av parametern `config`.

Changed in Django 6.0:

`Lexeme` objects were added.

## `SearchRank`

class SearchRank(vector, query, weights=None, normalization=None, cover_density=False)

Hittills har vi returnerat de resultat för vilka någon matchning mellan vektorn och frågan är möjlig. Det är troligt att du kanske vill ordna resultaten efter någon form av relevans. PostgreSQL tillhandahåller en rankningsfunktion som tar hänsyn till hur ofta frågetermerna visas i dokumentet, hur nära varandra termerna är i dokumentet och hur viktig den del av dokumentet är där de förekommer. Ju bättre matchning, desto högre värde på rankningen. För att beställa efter relevans:

    >>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
    >>> vector = SearchVector("body_text")
    >>> query = SearchQuery("cheese")
    >>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by("-rank")
    <QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]>

Se Viktning av frågor för en förklaring av parametern `weights`.

Ställ in parametern `cover_density` på `True` för att aktivera täckningsdensitetsrankningen, vilket innebär att närheten mellan matchande söktermer beaktas.

Ange ett heltal till parametern `normalization` för att styra normalisering av rangordning. Detta heltal är en bitmask, så att du kan kombinera flera beteenden:

    >>> from django.db.models import Value
    >>> Entry.objects.annotate(
    ...     rank=SearchRank(
    ...         vector,
    ...         query,
    ...         normalization=Value(2).bitor(Value(4)),
    ...     )
    ... )

PostgreSQL-dokumentationen har mer information om olika rangnormaliseringsalternativ.

## `Sökhuvud`

class SearchHeadline(expression, query, config=None, start_sel=None, stop_sel=None, max_words=None, min_words=None, short_word=None, highlight_all=None, max_fragments=None, fragment_delimiter=None)

Accepterar ett enda textfält eller ett uttryck, en fråga, en konfiguration och en uppsättning alternativ. Returnerar markerade sökresultat.

Ställ in parametrarna `start_sel` och `stop_sel` till strängvärdena som ska användas för att linda markerade frågetermer i dokumentet. PostgreSQL: s standardvärden är `<b>` och `</b>`.

Ge heltalsvärden till parametrarna `max_words` och `min_words` för att bestämma de längsta och kortaste rubrikerna. PostgreSQL: s standardvärden är 35 och 15.

Ge ett heltalsvärde till parametern `short_word` för att kassera ord av denna längd eller mindre i varje rubrik. PostgreSQL: s standard är 3.

Ställ in parametern `highlight_all` till `True` för att använda hela dokumentet i stället för ett fragment och ignorera parametrarna `max_words`, `min_words` och `short_word`. Det är inaktiverat som standard i PostgreSQL.

Ge ett heltalsvärde som inte är noll till `max_fragments` för att ställa in det maximala antalet fragment som ska visas. Det är inaktiverat som standard i PostgreSQL.

Ställ in strängparametern `fragment_delimiter` för att konfigurera avgränsaren mellan fragment. PostgreSQL: s standard är `" ... "`.

PostgreSQL-dokumentationen har mer information om upphighlighting search results.

Exempel på användning:

    >>> from django.contrib.postgres.search import SearchHeadline, SearchQuery
    >>> query = SearchQuery("red tomato")
    >>> entry = Entry.objects.annotate(
    ...     headline=SearchHeadline(
    ...         "body_text",
    ...         query,
    ...         start_sel="<span>",
    ...         stop_sel="</span>",
    ...     ),
    ... ).get()
    >>> print(entry.headline)
    Sandwich with <span>tomato</span> and <span>red</span> cheese.

Se Ändra sökkonfigurationen för en förklaring av parametern `config`.

## Ändra sökkonfigurationen

Du kan ange attributet `config` till en `SearchVector` och `SearchQuery` för att använda en annan sökkonfiguration. Detta gör det möjligt att använda olika språkparsers och ordböcker som definieras av databasen:

    >>> from django.contrib.postgres.search import SearchQuery, SearchVector
    >>> Entry.objects.annotate(
    ...     search=SearchVector("body_text", config="french"),
    ... ).filter(search=SearchQuery("œuf", config="french"))
    <QuerySet [<Entry: Pain perdu>]>

Värdet på `config` kan också lagras i en annan kolumn:

    >>> from django.db.models import F
    >>> Entry.objects.annotate(
    ...     search=SearchVector("body_text", config=F("blog__language")),
    ... ).filter(search=SearchQuery("œuf", config=F("blog__language")))
    <QuerySet [<Entry: Pain perdu>]>

## Viktning av frågor

Alla fält kanske inte har samma relevans i en fråga, så du kan ställa in vikter för olika vektorer innan du kombinerar dem:

    >>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
    >>> vector = SearchVector("body_text", weight="A") + SearchVector(
    ...     "blog__tagline", weight="B"
    ... )
    >>> query = SearchQuery("cheese")
    >>> Entry.objects.annotate(rank=SearchRank(vector, query)).filter(rank__gte=0.3).order_by(
    ...     "rank"
    ... )

Vikten ska vara en av följande bokstäver: D, C, B, A. Som standard hänvisar dessa vikter till siffrorna `0,1`, `0,2`, `0,4` respektive `1,0`. Om du vill vikta dem annorlunda, skicka en lista med fyra flyttal till `SearchRank` som `vikter` i samma ordning som ovan:

    >>> 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`

New in Django 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:

    >>> 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>]>

    >>> 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:

    >>> 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 []>

## Prestanda

Det krävs ingen särskild databaskonfiguration för att använda någon av dessa funktioner, men om du söker efter mer än några hundra poster kommer du sannolikt att stöta på prestandaproblem. Fulltextsökning är en mer intensiv process än att t.ex. jämföra storleken på ett heltal.

In the event that all the fields you’re querying on are contained within one particular model, you can create a functional `GinIndex` or `GistIndex` which matches the search vector you wish to use. For example:

    GinIndex(
        SearchVector("body_text", "headline", config="english"),
        name="search_vector_idx",
    )

The PostgreSQL docs has details on creating indexes for full text search.

### `SökVektorField`

class SearchVectorField

Om detta tillvägagångssätt blir för långsamt kan du lägga till en `SearchVectorField` i din modell. Du måste hålla den befolkad med triggers, till exempel, som beskrivs i PostgreSQL-dokumentationen. Du kan sedan fråga fältet som om det var en annoterad `SearchVector`:

    >>> Entry.objects.update(search_vector=SearchVector("body_text"))
    >>> Entry.objects.filter(search_vector="cheese")
    <QuerySet [<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]>

### Using `GeneratedField`

An alternative method is to use a `GeneratedField`, which has PostgreSQL maintain the column rather than a trigger:

    from django.contrib.postgres.indexes import GinIndex
    from django.contrib.postgres.search import SearchVector, SearchVectorField
    from django.db import models

    class Entry(models.Model):
        headline = models.CharField(max_length=255)
        body_text = models.TextField()

        search_vector = models.GeneratedField(
            expression=SearchVector("headline", weight="A", config="english")
            + SearchVector("body_text", weight="B", config="english"),
            output_field=SearchVectorField(),
            db_persist=True,
        )

        class Meta:
            indexes = [GinIndex(fields=["search_vector"])]

## Likhet mellan trigram

En annan metod för sökning är trigramlikhet. Ett trigram är en grupp med tre på varandra följande tecken. Förutom uppslagen `trigram_similar`, `trigram_word_similar` och `trigram_strict_word_similar` kan du använda ett par andra uttryck.

För att använda dem måste du aktivera pg_trgm-tillägget på PostgreSQL. Du kan installera den med hjälp av `TrigramExtension` migreringsoperation.

### `TrigramSimilarity`

class TrigramSimilarity(expression, string, **extra)

Accepterar ett fältnamn eller uttryck och en sträng eller ett uttryck. Returnerar trigramlikheten mellan de två argumenten.

Exempel på användning:

    >>> from django.contrib.postgres.search import TrigramSimilarity
    >>> Author.objects.create(name="Katy Stevens")
    >>> Author.objects.create(name="Stephen Keats")
    >>> test = "Katie Stephens"
    >>> Author.objects.annotate(
    ...     similarity=TrigramSimilarity("name", test),
    ... ).filter(
    ...     similarity__gt=0.3
    ... ).order_by("-similarity")
    <QuerySet [<Author: Katy Stevens>, <Author: Stephen Keats>]>

### `Trigramordlikhet`

class TrigramWordSimilarity(string, expression, **extra)

Accepterar en sträng eller ett uttryck och ett fältnamn eller ett uttryck. Returnerar trigramordlikheten mellan de två argumenten.

Exempel på användning:

    >>> from django.contrib.postgres.search import TrigramWordSimilarity
    >>> Author.objects.create(name="Katy Stevens")
    >>> Author.objects.create(name="Stephen Keats")
    >>> test = "Kat"
    >>> Author.objects.annotate(
    ...     similarity=TrigramWordSimilarity(test, "name"),
    ... ).filter(
    ...     similarity__gt=0.3
    ... ).order_by("-similarity")
    <QuerySet [<Author: Katy Stevens>]>

### `TrigramStrictWordSimilarity`

class TrigramStrictWordSimilarity(string, expression, **extra)

Accepterar en sträng eller ett uttryck och ett fältnamn eller ett uttryck. Returnerar den trigramstrikta ordlikheten mellan de två argumenten. Liknar `TrigramWordSimilarity()`, förutom att den tvingar gränser för utsträckning att matcha ordgränser.

### `TrigramDistance`

class TrigramDistance(expression, string, **extra)

Accepterar ett fältnamn eller uttryck och en sträng eller ett uttryck. Returnerar trigramavståndet mellan de två argumenten.

Exempel på användning:

    >>> from django.contrib.postgres.search import TrigramDistance
    >>> Author.objects.create(name="Katy Stevens")
    >>> Author.objects.create(name="Stephen Keats")
    >>> test = "Katie Stephens"
    >>> Author.objects.annotate(
    ...     distance=TrigramDistance("name", test),
    ... ).filter(
    ...     distance__lte=0.7
    ... ).order_by("distance")
    <QuerySet [<Author: Katy Stevens>, <Author: Stephen Keats>]>

### `TrigramWordDistance`

class TrigramWordDistance(string, expression, **extra)

Accepterar en sträng eller ett uttryck och ett fältnamn eller ett uttryck. Returnerar trigramordavståndet mellan de två argumenten.

Exempel på användning:

    >>> from django.contrib.postgres.search import TrigramWordDistance
    >>> Author.objects.create(name="Katy Stevens")
    >>> Author.objects.create(name="Stephen Keats")
    >>> test = "Kat"
    >>> Author.objects.annotate(
    ...     distance=TrigramWordDistance(test, "name"),
    ... ).filter(
    ...     distance__lte=0.7
    ... ).order_by("distance")
    <QuerySet [<Author: Katy Stevens>]>

### `TrigramStrictWordDistance`

class TrigramStrictWordDistance(string, expression, **extra)

Accepterar en sträng eller ett uttryck och ett fältnamn eller ett uttryck. Returnerar det trigramstrikta ordavståndet mellan de två argumenten.