mirror of
https://github.com/Hopiu/django-watson.git
synced 2026-03-17 06:00:24 +00:00
Added in tests for complex registration and multiple search engines.
This commit is contained in:
parent
f07ce3080f
commit
87bae74871
3 changed files with 52 additions and 22 deletions
|
|
@ -1,6 +1,6 @@
|
|||
"""Search backends used by django-watson."""
|
||||
|
||||
import re, operator
|
||||
import re
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
|
@ -28,7 +28,7 @@ class SearchBackend(object):
|
|||
|
||||
supports_ranking = False
|
||||
|
||||
def do_search(self, queryset, search_text):
|
||||
def do_search(self, engine_slug, queryset, search_text):
|
||||
"""Filters the given queryset according the the search logic for this backend."""
|
||||
word_queries = []
|
||||
for word in search_text.split():
|
||||
|
|
@ -39,7 +39,7 @@ class SearchBackend(object):
|
|||
word_query
|
||||
)
|
||||
|
||||
def do_search_ranking(self, queryset, search_text):
|
||||
def do_search_ranking(self, engine_slug, queryset, search_text):
|
||||
"""Ranks the given queryset according to the relevance of the given search text."""
|
||||
return queryset.extra(
|
||||
select = {
|
||||
|
|
@ -47,18 +47,17 @@ class SearchBackend(object):
|
|||
},
|
||||
)
|
||||
|
||||
def do_filter(self, queryset, search_text):
|
||||
def do_filter(self, engine_slug, queryset, search_text):
|
||||
"""Filters the given queryset according the the search logic for this backend."""
|
||||
word_queries = []
|
||||
word_query = Q(searchentry_set__engine_slug=engine_slug)
|
||||
for word in search_text.split():
|
||||
regex = regex_from_word(word)
|
||||
word_queries.append(Q(searchentry_set__title__iregex=regex) | Q(searchentry_set__content__iregex=regex) | Q(searchentry_set__content__iregex=regex))
|
||||
word_query = reduce(operator.and_, word_queries)
|
||||
word_query &= (Q(searchentry_set__title__iregex=regex) | Q(searchentry_set__content__iregex=regex) | Q(searchentry_set__content__iregex=regex))
|
||||
return queryset.filter(
|
||||
word_query
|
||||
)
|
||||
|
||||
def do_filter_ranking(self, queryset, search_text):
|
||||
def do_filter_ranking(self, engine_slug, queryset, search_text):
|
||||
"""Ranks the given queryset according to the relevance of the given search text."""
|
||||
return queryset.extra(
|
||||
select = {
|
||||
|
|
@ -114,14 +113,14 @@ class PostgresSearchBackend(SearchBackend):
|
|||
|
||||
supports_ranking = True
|
||||
|
||||
def do_search(self, queryset, search_text):
|
||||
def do_search(self, engine_slug, queryset, search_text):
|
||||
"""Performs the full text search."""
|
||||
return queryset.extra(
|
||||
where = ("search_tsv @@ plainto_tsquery(%s)",),
|
||||
params = (search_text,),
|
||||
)
|
||||
|
||||
def do_search_ranking(self, queryset, search_text):
|
||||
def do_search_ranking(self, engine_slug, queryset, search_text):
|
||||
"""Performs full text ranking."""
|
||||
return queryset.extra(
|
||||
select = {
|
||||
|
|
@ -131,7 +130,7 @@ class PostgresSearchBackend(SearchBackend):
|
|||
order_by = ("-watson_rank",),
|
||||
)
|
||||
|
||||
def do_filter(self, queryset, search_text):
|
||||
def do_filter(self, engine_slug, queryset, search_text):
|
||||
"""Performs the full text filter."""
|
||||
model = queryset.model
|
||||
content_type = ContentType.objects.get_for_model(model)
|
||||
|
|
@ -142,6 +141,7 @@ class PostgresSearchBackend(SearchBackend):
|
|||
return queryset.extra(
|
||||
tables = ("watson_searchentry",),
|
||||
where = (
|
||||
"watson_searchentry.engine_slug = %s",
|
||||
"watson_searchentry.search_tsv @@ plainto_tsquery(%s)",
|
||||
"watson_searchentry.{ref_name} = {table_name}.{pk_name}".format(
|
||||
ref_name = ref_name,
|
||||
|
|
@ -150,10 +150,10 @@ class PostgresSearchBackend(SearchBackend):
|
|||
),
|
||||
"watson_searchentry.content_type_id = %s"
|
||||
),
|
||||
params = (search_text, content_type.id),
|
||||
params = (engine_slug, search_text, content_type.id),
|
||||
)
|
||||
|
||||
def do_filter_ranking(self, queryset, search_text):
|
||||
def do_filter_ranking(self, engine_slug, queryset, search_text):
|
||||
"""Performs the full text ranking."""
|
||||
return queryset.extra(
|
||||
select = {
|
||||
|
|
|
|||
|
|
@ -452,10 +452,10 @@ class SearchEngine(object):
|
|||
)
|
||||
# Perform the backend-specific full text match.
|
||||
backend = get_backend()
|
||||
queryset = backend.do_search(queryset, search_text)
|
||||
queryset = backend.do_search(self._engine_slug, queryset, search_text)
|
||||
# Perform the backend-specific full-text ranking.
|
||||
if ranking:
|
||||
queryset = backend.do_search_ranking(queryset, search_text)
|
||||
queryset = backend.do_search_ranking(self._engine_slug, queryset, search_text)
|
||||
# Return the complete queryset.
|
||||
return queryset
|
||||
|
||||
|
|
@ -469,10 +469,10 @@ class SearchEngine(object):
|
|||
queryset = queryset._default_manager.all()
|
||||
# Perform the backend-specific full text match.
|
||||
backend = get_backend()
|
||||
queryset = backend.do_filter(queryset, search_text)
|
||||
queryset = backend.do_filter(self._engine_slug, queryset, search_text)
|
||||
# Perform the backend-specific full-text ranking.
|
||||
if ranking:
|
||||
queryset = backend.do_filter_ranking(queryset, search_text)
|
||||
queryset = backend.do_filter_ranking(self._engine_slug, queryset, search_text)
|
||||
# Return the complete queryset.
|
||||
return queryset
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from django.core.management import call_command
|
|||
from django.conf.urls.defaults import *
|
||||
|
||||
import watson
|
||||
from watson.registration import RegistrationError, get_backend
|
||||
from watson.registration import RegistrationError, get_backend, SearchEngine
|
||||
from watson.models import SearchEntry
|
||||
|
||||
|
||||
|
|
@ -85,6 +85,9 @@ class RegistrationTest(TestCase):
|
|||
self.assertRaises(RegistrationError, lambda: isinstance(watson.get_adapter(TestModel1)))
|
||||
|
||||
|
||||
complex_registration_search_engine = SearchEngine("restricted")
|
||||
|
||||
|
||||
class SearchTestBase(TestCase):
|
||||
|
||||
live_filter = False
|
||||
|
|
@ -98,6 +101,8 @@ class SearchTestBase(TestCase):
|
|||
# Register the test models.
|
||||
watson.register(TestModel1, live_filter=self.live_filter)
|
||||
watson.register(TestModel2, exclude=("id",), live_filter=self.live_filter)
|
||||
complex_registration_search_engine.register(TestModel1, exclude=("content", "description",), store=("is_published",))
|
||||
complex_registration_search_engine.register(TestModel2, fields=("title",))
|
||||
# Create some test models.
|
||||
self.test11 = TestModel1.objects.create(
|
||||
title = "title model1 instance11",
|
||||
|
|
@ -127,6 +132,8 @@ class SearchTestBase(TestCase):
|
|||
# Unregister the test models.
|
||||
watson.unregister(TestModel1)
|
||||
watson.unregister(TestModel2)
|
||||
complex_registration_search_engine.unregister(TestModel1)
|
||||
complex_registration_search_engine.unregister(TestModel2)
|
||||
# Delete the test models.
|
||||
TestModel1.objects.all().delete()
|
||||
TestModel2.objects.all().delete()
|
||||
|
|
@ -141,7 +148,7 @@ class SearchTestBase(TestCase):
|
|||
class InternalsTest(SearchTestBase):
|
||||
|
||||
def testSearchEntriesCreated(self):
|
||||
self.assertEqual(SearchEntry.objects.count(), 4)
|
||||
self.assertEqual(SearchEntry.objects.filter(engine_slug="default").count(), 4)
|
||||
|
||||
def testBuildWatsonCommand(self):
|
||||
# This update won't take affect, because no search context is active.
|
||||
|
|
@ -168,16 +175,17 @@ class InternalsTest(SearchTestBase):
|
|||
self.assertEqual(watson.search("foo").count(), 0)
|
||||
|
||||
def testFixesDuplicateSearchEntries(self):
|
||||
search_entries = SearchEntry.objects.filter(engine_slug="default")
|
||||
# Duplicate a couple of search entries.
|
||||
for search_entry in SearchEntry.objects.all()[:2]:
|
||||
for search_entry in search_entries.all()[:2]:
|
||||
search_entry.id = None
|
||||
search_entry.save()
|
||||
# Make sure that we have six (including duplicates).
|
||||
self.assertEqual(SearchEntry.objects.count(), 6)
|
||||
self.assertEqual(search_entries.all().count(), 6)
|
||||
# Run the rebuild command.
|
||||
call_command("buildwatson", verbosity=0)
|
||||
# Make sure that we have four again (including duplicates).
|
||||
self.assertEqual(SearchEntry.objects.count(), 4)
|
||||
self.assertEqual(search_entries.all().count(), 4)
|
||||
|
||||
def testSearchEmailParts(self):
|
||||
with watson.context():
|
||||
|
|
@ -393,6 +401,28 @@ class RankingTest(SearchTestBase):
|
|||
)
|
||||
|
||||
|
||||
class ComplexRegistrationTest(SearchTestBase):
|
||||
|
||||
def testMetaStored(self):
|
||||
self.assertEqual(complex_registration_search_engine.search("instance11")[0].meta["is_published"], True)
|
||||
|
||||
def testMetaNotStored(self):
|
||||
self.assertRaises(KeyError, lambda: complex_registration_search_engine.search("instance21")[0].meta["is_published"])
|
||||
|
||||
def testFieldsExcludedOnSearch(self):
|
||||
self.assertEqual(complex_registration_search_engine.search("TITLE").count(), 4)
|
||||
self.assertEqual(complex_registration_search_engine.search("CONTENT").count(), 0)
|
||||
self.assertEqual(complex_registration_search_engine.search("DESCRIPTION").count(), 0)
|
||||
|
||||
def testFieldsExcludedOnFilter(self):
|
||||
self.assertEqual(complex_registration_search_engine.filter(TestModel1, "TITLE").count(), 2)
|
||||
self.assertEqual(complex_registration_search_engine.filter(TestModel1, "CONTENT").count(), 0)
|
||||
self.assertEqual(complex_registration_search_engine.filter(TestModel1, "DESCRIPTION").count(), 0)
|
||||
self.assertEqual(complex_registration_search_engine.filter(TestModel2, "TITLE").count(), 2)
|
||||
self.assertEqual(complex_registration_search_engine.filter(TestModel2, "CONTENT").count(), 0)
|
||||
self.assertEqual(complex_registration_search_engine.filter(TestModel2, "DESCRIPTION").count(), 0)
|
||||
|
||||
|
||||
urlpatterns = patterns("watson.views",
|
||||
|
||||
url("^simple/$", "search", name="search_simple"),
|
||||
|
|
|
|||
Loading…
Reference in a new issue