Django - Full Text Search - Wildcard
Can I use wildcards in Django? Full text search?
https://docs.djangoproject.com/en/1.11/ref/contrib/postgres/search/
post = request.POST.get('search')
query = SearchQuery(post)
vector = SearchVector('headline', weight='A') + SearchVector('content', weight='B')
rank = SearchRank(vector, query, weights=[0.1,0.2])
data = wiki_entry.objects.annotate(rank=SearchRank(vector,query)).filter(rank__gte=0.1).order_by('-rank')
It currently matches only complete words.
Characters like *% | and have no effect.
Or do I need to go back to icons?
https://docs.djangoproject.com/en/1.11/ref/models/querysets/#icontains
Any help is appreciated
source to share
[Postgres' part] The Postgres manual only mentions this briefly ( https://www.postgresql.org/docs/current/static/textsearch-controls.html#TEXTSEARCH-PARSING-QUERIES ), but yes it is possible if you you just need to use the prefix:
test=# select to_tsvector('abcd') @@ to_tsquery('ab:*');
?column?
----------
t
(1 row)
test=# select to_tsvector('abcd') @@ to_tsquery('ac:*');
?column?
----------
f
(1 row)
And such a query will use the GIN index (I assume you have it).
[Django part] I'm not a Django user, so I did a quick research and found that unfortunately Django is using a plainto_tsquery()
function and not to_tsquery()
: https://docs.djangoproject.com/en/1.11/_modules/django/contrib/postgres / search / # SearchQuery
plainto_tsquery()
done for simplicity when you only use plain text as input - so it doesn't support extended queries:
test=# select to_tsvector('abcd') @@ plainto_tsquery('ab:*');
?column?
----------
f
(1 row)
test=# select to_tsvector('abcd') @@ plainto_tsquery('ac:*');
?column?
----------
f
(1 row)
So, in this case, I would recommend that you use plain SQL with to_tsquery()
. But you must be sure that you have filtered out all special characters (eg, &
or |
) from your text input, otherwise it to_tsquery()
will lead to incorrect results or even errors. Or if you can extend django.contrib.postgres.search to work with to_tsquery()
(this will be a big contribution, by the way).
Alternatives:
- If your data is ACSII only, you can use
LIKE
with the search prefix and B-tree index generated with operator classestext_pattern_ops
/varchar_pattern_ops
(if you need case insensitivity, use the functional index abovelower(column_name)
andlower(column_name) like '...%'
, see https://www.postgresql.org /docs/9.6/static/indexes-opclass.html ); - use the pg_trgm index which supports GiST / GIN regexes and indexes ( https://www.postgresql.org/docs/9.6/static/pgtrgm.html )
source to share