Coverage for databases/tests/test_full_text_search.py: 100%
40 statements
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-27 18:25 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2024-08-27 18:25 +0000
1from typing import Optional, cast
3import pytest
4from pydantic import BaseModel
6from prisma import Prisma
8from .._types import DatabaseMapping, SupportedDatabase
11# Define a class to hold the search queries
12class FullTextSearchSyntax(BaseModel):
13 search_or: str
14 search_and: str
17# Define the queries for MySQL
18_mysql_syntax = FullTextSearchSyntax(
19 search_or='cats dogs',
20 search_and='+cats +dogs',
21)
23# Define the queries for PostgreSQL
24_postgresql_syntax = FullTextSearchSyntax(
25 search_or='cats | dogs',
26 search_and='cats & dogs',
27)
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}
39@pytest.mark.asyncio
40async def test_full_text_search(client: Prisma) -> None:
41 """Ensure that full-text search works correctly on both PostgreSQL and MySQL"""
43 # Determine the correct syntax based on the database
44 db_type = cast(SupportedDatabase, client._active_provider)
45 syntax = FULL_TEXT_SEARCH_SYNTAX[db_type]
47 if syntax is None:
48 pytest.skip(f'Skipping test for {db_type}')
50 # Create some posts with varied content
51 await client.post.create_many(
52 data=[
53 {
54 'title': 'cats are great pets. dogs are loyal companions.',
55 'published': True,
56 },
57 {
58 'title': 'cats are independent and mysterious animals.',
59 'published': True,
60 },
61 {
62 'title': 'rabbits and hamsters are small and cute pets.',
63 'published': True,
64 },
65 ]
66 )
68 # Test: Search for posts that contain 'cats' or 'dogs'
69 posts = await client.post.find_many(
70 where={
71 'title': {
72 'search': syntax.search_or,
73 },
74 }
75 )
76 assert len(posts) == 2
77 for post in posts:
78 assert 'cats' in post.title or 'dogs' in post.title
80 # Test: Search for posts that contain both 'cats' and 'dogs'
81 posts = await client.post.find_many(
82 where={
83 'title': {
84 'search': syntax.search_and,
85 },
86 }
87 )
88 assert len(posts) == 1
89 assert 'cats' in posts[0].title
90 assert 'dogs' in posts[0].title
93@pytest.mark.asyncio
94async def test_order_by_relevance(client: Prisma) -> None:
95 """Ensure that ordering by relevance works correctly on both PostgreSQL and MySQL"""
97 # Determine the correct syntax based on the database
98 db_type = cast(SupportedDatabase, client._active_provider)
99 syntax = FULL_TEXT_SEARCH_SYNTAX[db_type]
101 if syntax is None:
102 pytest.skip(f'Skipping test for {db_type}')
104 # Create some posts with varied content
105 await client.post.create_many(
106 data=[
107 {
108 'title': 'cats are great pets. dogs are loyal companions.',
109 'published': True,
110 },
111 {
112 'title': 'cats are independent and mysterious animals.',
113 'published': True,
114 },
115 {
116 'title': 'rabbits and hamsters are small and cute pets.',
117 'published': True,
118 },
119 ]
120 )
122 # Test: Order posts by relevance descending
123 post = await client.post.find_first(
124 order={
125 '_relevance': {
126 'fields': ['title'],
127 'search': syntax.search_or,
128 'sort': 'desc',
129 },
130 }
131 )
132 assert post is not None
133 assert 'cats' in post.title
134 assert 'dogs' in post.title
136 # Test: Order posts by relevance ascending
137 post = await client.post.find_first(
138 order={
139 '_relevance': {
140 'fields': ['title'],
141 'search': syntax.search_or,
142 'sort': 'asc',
143 },
144 }
145 )
146 assert post is not None
147 assert 'rabbits' in post.title