test_trigram.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. from django.test import modify_settings
  2. from . import PostgreSQLTestCase
  3. from .models import CharFieldModel, TextFieldModel
  4. try:
  5. from django.contrib.postgres.search import (
  6. TrigramDistance, TrigramSimilarity,
  7. )
  8. except ImportError:
  9. pass
  10. @modify_settings(INSTALLED_APPS={'append': 'django.contrib.postgres'})
  11. class TrigramTest(PostgreSQLTestCase):
  12. Model = CharFieldModel
  13. @classmethod
  14. def setUpTestData(cls):
  15. cls.Model.objects.bulk_create([
  16. cls.Model(field='Matthew'),
  17. cls.Model(field='Cat sat on mat.'),
  18. cls.Model(field='Dog sat on rug.'),
  19. ])
  20. def test_trigram_search(self):
  21. self.assertQuerysetEqual(
  22. self.Model.objects.filter(field__trigram_similar='Mathew'),
  23. ['Matthew'],
  24. transform=lambda instance: instance.field,
  25. )
  26. def test_trigram_similarity(self):
  27. search = 'Bat sat on cat.'
  28. # Round result of similarity because PostgreSQL 12+ uses greater
  29. # precision.
  30. self.assertQuerysetEqual(
  31. self.Model.objects.filter(
  32. field__trigram_similar=search,
  33. ).annotate(similarity=TrigramSimilarity('field', search)).order_by('-similarity'),
  34. [('Cat sat on mat.', 0.625), ('Dog sat on rug.', 0.333333)],
  35. transform=lambda instance: (instance.field, round(instance.similarity, 6)),
  36. ordered=True,
  37. )
  38. def test_trigram_similarity_alternate(self):
  39. # Round result of distance because PostgreSQL 12+ uses greater
  40. # precision.
  41. self.assertQuerysetEqual(
  42. self.Model.objects.annotate(
  43. distance=TrigramDistance('field', 'Bat sat on cat.'),
  44. ).filter(distance__lte=0.7).order_by('distance'),
  45. [('Cat sat on mat.', 0.375), ('Dog sat on rug.', 0.666667)],
  46. transform=lambda instance: (instance.field, round(instance.distance, 6)),
  47. ordered=True,
  48. )
  49. class TrigramTextFieldTest(TrigramTest):
  50. """
  51. TextField has the same behavior as CharField regarding trigram lookups.
  52. """
  53. Model = TextFieldModel