#27732: django.contrib.postgres.search SearchRank doesn't handle
SearchVectorField
references
--------------------------------------------+------------------------
Reporter: matt-hoskins | Owner: (none)
Type: Bug | Status: new
Component: contrib.postgres | Version: 1.10
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
--------------------------------------------+------------------------
For search performance I'm using SearchVectorField on a model. However if
I reference that field in the vector argument to SearchRank I get an
error. This is because SearchRank always wraps a vector argument that
lacks a "resolve_expression" attribute as a SearchVector even if it would
end up resolving to a SearchVectorField.
If I modify tests/postgres_tests/test_search.py and add the following to
the SearchVectorFieldTest class:
{{{#!python
def test_existing_vector_ranking(self):
Line.objects.update(dialogue_search_vector=SearchVector('dialogue'))
searched = Line.objects.filter(character=self.minstrel).annotate(
rank=SearchRank('dialogue_search_vector', SearchQuery('brave
sir robin')),
).order_by('rank')
self.assertSequenceEqual(searched, [self.verse2, self.verse1,
self.verse0])
}}}
Then this results in the following error:
{{{
ProgrammingError: function to_tsvector(tsvector) does not exist
LINE 1: ... "postgres_tests_line"."dialogue_config", ts_rank(to_tsvecto...
^
HINT: No function matches the given name and argument types. You might
need to add explicit type casts.
}}}
As the enforced wrapping of the vector argument in a SearchVector is then
causing the sql to wrap the tsvector field in a coalesce (which doesn't
cause an issue) and then a to_tsvector call.
I've not delved into the Expressions code before (my last rummaging around
in the bowels of the query code was a few years ago) but from my quick
look at existing code and the APIs then perhaps a solution is for
SearchRank to not wrap the vector argument as it comes into __init__ but
instead have a resolve_expression call which checks the first resolved
expression on the result of calling super's resolve_expression is or isn't
of type SearchVectorField and then if it isn't then resolve a wrapped
version.
I've attached a patch which both adds the test I mention above (it may be
that it should live in the rank test rather than the search vector field
test, or have its own test class which covers the combination of both) and
also modifies SearchRank in the way I've suggested above. The postgres
tests pass on my test system with this patch.
--
Ticket URL: <https://code.djangoproject.com/ticket/27732>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/055.dec0dc5f540ea7cd185568a67565177d%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.