@@ -80,7 +80,7 @@ def test_create_table_and_insert():
8080
8181
8282def test_paradedb_pg_search_extension ():
83- """Test ParadeDB's pg_search extension for full-text search."""
83+ """Test ParadeDB's pg_search extension for full-text search using v2 API ."""
8484 conn = get_connection ()
8585 cursor = conn .cursor ()
8686
@@ -109,48 +109,47 @@ def test_paradedb_pg_search_extension():
109109 """ )
110110 conn .commit ()
111111
112- # Create BM25 search index using ParadeDB
112+ # Create BM25 search index using ParadeDB v2 API (CREATE INDEX syntax)
113113 cursor .execute (f"""
114- CALL paradedb.create_bm25(
115- index_name => '{ index_name } ',
116- table_name => '{ table_name } ',
117- key_field => 'id',
118- text_fields => paradedb.field('name') || paradedb.field('description')
119- );
114+ CREATE INDEX { index_name } ON { table_name }
115+ USING bm25 (id, name, description)
116+ WITH (key_field='id');
120117 """ )
121118 conn .commit ()
122119
123- # Search for products containing 'wireless'
120+ # Search for products containing 'wireless' using ||| operator (disjunction/OR)
124121 cursor .execute (f"""
125122 SELECT id, name, description
126- FROM { index_name } .search('description:wireless');
123+ FROM { table_name }
124+ WHERE description ||| 'wireless';
127125 """ )
128126 results = cursor .fetchall ()
129127
130128 assert len (results ) >= 1
131129 assert any ("Headphones" in row [1 ] for row in results )
132130
133- # Search for products containing 'laptop'
131+ # Search for products containing 'laptop' in name or description
134132 cursor .execute (f"""
135133 SELECT id, name, description
136- FROM { index_name } .search('name:laptop OR description:laptop');
134+ FROM { table_name }
135+ WHERE name ||| 'laptop' OR description ||| 'laptop';
137136 """ )
138137 results = cursor .fetchall ()
139138
140139 assert len (results ) >= 1
141140 assert any ("Laptop" in row [1 ] for row in results )
142141
143142 finally :
144- # Cleanup
145- cursor .execute (f"CALL paradedb.drop_bm25(' { index_name } ') ;" )
143+ # Cleanup - drop index first, then table
144+ cursor .execute (f"DROP INDEX IF EXISTS { index_name } ;" )
146145 cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
147146 conn .commit ()
148147 cursor .close ()
149148 conn .close ()
150149
151150
152- def test_paradedb_hybrid_search ():
153- """Test ParadeDB's hybrid search capabilities ."""
151+ def test_paradedb_search_with_scoring ():
152+ """Test ParadeDB's BM25 search with relevance scoring ."""
154153 conn = get_connection ()
155154 cursor = conn .cursor ()
156155
@@ -179,21 +178,19 @@ def test_paradedb_hybrid_search():
179178 """ )
180179 conn .commit ()
181180
182- # Create search index
181+ # Create search index using v2 API
183182 cursor .execute (f"""
184- CALL paradedb.create_bm25(
185- index_name => '{ index_name } ',
186- table_name => '{ table_name } ',
187- key_field => 'id',
188- text_fields => paradedb.field('title') || paradedb.field('content')
189- );
183+ CREATE INDEX { index_name } ON { table_name }
184+ USING bm25 (id, title, content)
185+ WITH (key_field='id');
190186 """ )
191187 conn .commit ()
192188
193- # Search for programming-related documents
189+ # Search for programming-related documents with scoring
194190 cursor .execute (f"""
195- SELECT id, title, paradedb.score(id) as score
196- FROM { index_name } .search('content:programming')
191+ SELECT id, title, pdb.score(id) as score
192+ FROM { table_name }
193+ WHERE content ||| 'programming'
197194 ORDER BY score DESC;
198195 """ )
199196 results = cursor .fetchall ()
@@ -205,7 +202,65 @@ def test_paradedb_hybrid_search():
205202
206203 finally :
207204 # Cleanup
208- cursor .execute (f"CALL paradedb.drop_bm25('{ index_name } ');" )
205+ cursor .execute (f"DROP INDEX IF EXISTS { index_name } ;" )
206+ cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
207+ conn .commit ()
208+ cursor .close ()
209+ conn .close ()
210+
211+
212+ def test_paradedb_conjunction_search ():
213+ """Test ParadeDB's conjunction (AND) search using &&& operator."""
214+ conn = get_connection ()
215+ cursor = conn .cursor ()
216+
217+ table_name = f"items_{ short_uid ()} "
218+ index_name = f"{ table_name } _idx"
219+
220+ try :
221+ # Create table
222+ cursor .execute (f"""
223+ CREATE TABLE { table_name } (
224+ id SERIAL PRIMARY KEY,
225+ name TEXT NOT NULL,
226+ description TEXT
227+ );
228+ """ )
229+ conn .commit ()
230+
231+ # Insert sample data
232+ cursor .execute (f"""
233+ INSERT INTO { table_name } (name, description) VALUES
234+ ('Running Shoes', 'Lightweight running shoes for marathon training'),
235+ ('Walking Shoes', 'Comfortable walking shoes for daily use'),
236+ ('Running Gear', 'Essential gear for running enthusiasts'),
237+ ('Basketball Shoes', 'High-top basketball shoes with ankle support');
238+ """ )
239+ conn .commit ()
240+
241+ # Create BM25 index
242+ cursor .execute (f"""
243+ CREATE INDEX { index_name } ON { table_name }
244+ USING bm25 (id, name, description)
245+ WITH (key_field='id');
246+ """ )
247+ conn .commit ()
248+
249+ # Search using conjunction (AND) - must contain both 'running' AND 'shoes'
250+ cursor .execute (f"""
251+ SELECT id, name, description
252+ FROM { table_name }
253+ WHERE name &&& 'running shoes';
254+ """ )
255+ results = cursor .fetchall ()
256+
257+ assert len (results ) >= 1
258+ # Should match "Running Shoes" but not "Running Gear" or "Walking Shoes"
259+ assert any ("Running Shoes" in row [1 ] for row in results )
260+
261+ finally :
262+ # Cleanup
263+ cursor .execute (f"DROP INDEX IF EXISTS { index_name } ;" )
209264 cursor .execute (f"DROP TABLE IF EXISTS { table_name } ;" )
210265 conn .commit ()
211266 cursor .close ()
0 commit comments