Coverage for databases/sync_tests/test_full_text_search.py: 100%

38 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-08-27 18:25 +0000

1from typing import Optional, cast 

2 

3import pytest 

4from pydantic import BaseModel 

5 

6from prisma import Prisma 

7 

8from .._types import DatabaseMapping, SupportedDatabase 

9 

10 

11# Define a class to hold the search queries 

12class FullTextSearchSyntax(BaseModel): 

13 search_or: str 

14 search_and: str 

15 

16 

17# Define the queries for MySQL 

18_mysql_syntax = FullTextSearchSyntax( 

19 search_or='cats dogs', 

20 search_and='+cats +dogs', 

21) 

22 

23# Define the queries for PostgreSQL 

24_postgresql_syntax = FullTextSearchSyntax( 

25 search_or='cats | dogs', 

26 search_and='cats & dogs', 

27) 

28 

29# Map the syntax to the corresponding database 

30FULL_TEXT_SEARCH_SYNTAX: DatabaseMapping[Optional[FullTextSearchSyntax]] = { 

31 'mysql': _mysql_syntax, 

32 'postgresql': _postgresql_syntax, 

33 'cockroachdb': None, 

34 'mariadb': None, 

35 'sqlite': None, 

36} 

37 

38 

39def test_full_text_search(client: Prisma) -> None: 

40 """Ensure that full-text search works correctly on both PostgreSQL and MySQL""" 

41 

42 # Determine the correct syntax based on the database 

43 db_type = cast(SupportedDatabase, client._active_provider) 

44 syntax = FULL_TEXT_SEARCH_SYNTAX[db_type] 

45 

46 if syntax is None: 

47 pytest.skip(f'Skipping test for {db_type}') 

48 

49 # Create some posts with varied content 

50 client.post.create_many( 

51 data=[ 

52 { 

53 'title': 'cats are great pets. dogs are loyal companions.', 

54 'published': True, 

55 }, 

56 { 

57 'title': 'cats are independent and mysterious animals.', 

58 'published': True, 

59 }, 

60 { 

61 'title': 'rabbits and hamsters are small and cute pets.', 

62 'published': True, 

63 }, 

64 ] 

65 ) 

66 

67 # Test: Search for posts that contain 'cats' or 'dogs' 

68 posts = client.post.find_many( 

69 where={ 

70 'title': { 

71 'search': syntax.search_or, 

72 }, 

73 } 

74 ) 

75 assert len(posts) == 2 

76 for post in posts: 

77 assert 'cats' in post.title or 'dogs' in post.title 

78 

79 # Test: Search for posts that contain both 'cats' and 'dogs' 

80 posts = client.post.find_many( 

81 where={ 

82 'title': { 

83 'search': syntax.search_and, 

84 }, 

85 } 

86 ) 

87 assert len(posts) == 1 

88 assert 'cats' in posts[0].title 

89 assert 'dogs' in posts[0].title 

90 

91 

92def test_order_by_relevance(client: Prisma) -> None: 

93 """Ensure that ordering by relevance works correctly on both PostgreSQL and MySQL""" 

94 

95 # Determine the correct syntax based on the database 

96 db_type = cast(SupportedDatabase, client._active_provider) 

97 syntax = FULL_TEXT_SEARCH_SYNTAX[db_type] 

98 

99 if syntax is None: 

100 pytest.skip(f'Skipping test for {db_type}') 

101 

102 # Create some posts with varied content 

103 client.post.create_many( 

104 data=[ 

105 { 

106 'title': 'cats are great pets. dogs are loyal companions.', 

107 'published': True, 

108 }, 

109 { 

110 'title': 'cats are independent and mysterious animals.', 

111 'published': True, 

112 }, 

113 { 

114 'title': 'rabbits and hamsters are small and cute pets.', 

115 'published': True, 

116 }, 

117 ] 

118 ) 

119 

120 # Test: Order posts by relevance descending 

121 post = client.post.find_first( 

122 order={ 

123 '_relevance': { 

124 'fields': ['title'], 

125 'search': syntax.search_or, 

126 'sort': 'desc', 

127 }, 

128 } 

129 ) 

130 assert post is not None 

131 assert 'cats' in post.title 

132 assert 'dogs' in post.title 

133 

134 # Test: Order posts by relevance ascending 

135 post = client.post.find_first( 

136 order={ 

137 '_relevance': { 

138 'fields': ['title'], 

139 'search': syntax.search_or, 

140 'sort': 'asc', 

141 }, 

142 } 

143 ) 

144 assert post is not None 

145 assert 'rabbits' in post.title