La feature di Django per la ricerca fulltext su campi di DB, almeno sino alla versione 4.0, viene supportata direttamente solo su PostgreSQL.
Per quanto riguarda MySQL/MariaDB è necessario procedere con alcuni step manuali per definire l'indice in fase di migration e per implementare il metodo di search attraverso una Lookup custom.
Vediamo con ordine:
E' opportuno creare una migrazione vuota sulla quale lavorare. Ipotizziamo di avere un'app nomeapp e procediamo con:
./manage.py makemigrations --empty nomeapp
A questo punto andremo ad editare il file di migration generato, inserendo nelle operations la creazione/rimozione dell'indice fulltext sui campi/tabella desiderati
...
operations = [
migrations.RunSQL(
f"CREATE FULLTEXT INDEX nomeindice ON nometabella(nomecolonna)",
f"DROP INDEX nomeindice ON nometabella",
),
]
...
Andiamo quindi ad applicare la migrazione
./manage.py migrate nomeapp
e l'indice fulltext verrà creato.
A questo punto è necessario fornire a Django la possibilità di utilizzare questo indice, con la sintassi SQL appropriata, per le ricerche.
Per fare ciò definiamo una Lookup custom chiamata search che andremo a registrare sul modello TextField e/o sugli altri modelli per i quali abbiamo definito indici fulltext. Possiamo aggiungere direttamente in models.py:
class Search(models.Lookup):
lookup_name = "search"
def as_mysql(self, compiler, connection):
lhs, lhs_params = self.process_lhs(compiler, connection)
rhs, rhs_params = self.process_rhs(compiler, connection)
params = lhs_params + rhs_params
return f"MATCH (%s) AGAINST (%s IN BOOLEAN MODE)" % (lhs, rhs), params
models.TextField.register_lookup(Search)
Nulla ci vieta di estendere o definire altre tipologie di search nello stesso modo.
Per effettuare una search fulltext è sufficiente utilizzare la lookup search sul campo per il quale è stato definito l'indice fulltext:
Documento.objects.filter(nomecolonna__search='+Paroladaricercare')