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

+3


source to share


1 answer


[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 classes text_pattern_ops

    / varchar_pattern_ops

    (if you need case insensitivity, use the functional index above lower(column_name)

    and lower(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 )
+2


source







All Articles