pgvector-haystack 6.6.0__tar.gz → 6.6.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/CHANGELOG.md +69 -16
  2. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/PKG-INFO +1 -1
  3. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/document_stores/pgvector/document_store.py +8 -3
  4. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/document_stores/pgvector/filters.py +4 -0
  5. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/test_document_store.py +14 -0
  6. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/test_document_store_async.py +14 -0
  7. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/test_filters.py +18 -0
  8. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/.gitignore +0 -0
  9. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/LICENSE.txt +0 -0
  10. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/README.md +0 -0
  11. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/examples/embedding_retrieval.py +0 -0
  12. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/examples/hybrid_retrieval.py +0 -0
  13. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/pydoc/config_docusaurus.yml +0 -0
  14. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/pyproject.toml +0 -0
  15. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/components/retrievers/pgvector/__init__.py +0 -0
  16. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/components/retrievers/pgvector/embedding_retriever.py +0 -0
  17. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/components/retrievers/pgvector/keyword_retriever.py +0 -0
  18. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/components/retrievers/py.typed +0 -0
  19. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/document_stores/pgvector/__init__.py +0 -0
  20. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/document_stores/pgvector/converters.py +0 -0
  21. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/src/haystack_integrations/document_stores/py.typed +0 -0
  22. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/__init__.py +0 -0
  23. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/conftest.py +0 -0
  24. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/test_converters.py +0 -0
  25. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/test_retrieval.py +0 -0
  26. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/test_retrieval_async.py +0 -0
  27. {pgvector_haystack-6.6.0 → pgvector_haystack-6.6.1}/tests/test_retrievers.py +0 -0
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [integrations/pgvector-v6.6.0] - 2026-08-26
4
+
5
+ ### 🐛 Bug Fixes
6
+
7
+ - PGVector adding optional parameter `filters` to `get_metadata_field_unique_values()` (#3735)
8
+ - Standardize license files (#3771)
9
+
10
+ ### 🧪 Testing
11
+
12
+ - `PGVectorDocumentStore` removing duplicated tests already covered by haystack Mixin tests (#3783)
13
+
14
+ ### 🧹 Chores
15
+
16
+ - Re-standardize READMEs (#3768)
17
+
18
+
3
19
  ## [integrations/pgvector-v6.5.0] - 2026-08-03
4
20
 
5
21
  ### 🚀 Features
@@ -147,9 +163,14 @@
147
163
 
148
164
  ### 🧹 Chores
149
165
 
150
- - Remove black (#1985)
151
166
  - Pgvector - update docker image in examples (#1995)
152
167
 
168
+ ## [integrations/pgvector-v5.2.0] - 2025-06-26
169
+
170
+ ### 🧹 Chores
171
+
172
+ - Remove black (#1985)
173
+
153
174
 
154
175
  ## [integrations/pgvector-v3.4.1] - 2025-06-20
155
176
 
@@ -253,48 +274,75 @@
253
274
 
254
275
  ### 🚀 Features
255
276
 
256
- - Add filter_policy to pgvector integration (#820)
257
277
  - Add schema support to pgvector document store. (#1095)
258
278
  - Pgvector - recreate the connection if it is no longer valid (#1202)
259
279
 
260
- ### 🐛 Bug Fixes
261
-
262
- - `PgVector` - Fallback to default filter policy when deserializing retrievers without the init parameter (#900)
263
-
264
280
  ### 📚 Documentation
265
281
 
266
282
  - Explain different connection string formats in the docstring (#1132)
267
283
 
284
+ ### ⚙️ CI
285
+
286
+ - Adopt uv as installer (#1142)
287
+
288
+ ### 🧹 Chores
289
+
290
+ - Update changelog after removing legacy filters (#1083)
291
+ - Update ruff linting scripts and settings (#1105)
292
+
293
+ ## [integrations/pgvector-v1.0.0] - 2024-09-12
294
+
268
295
  ### 🧪 Testing
269
296
 
270
297
  - Do not retry tests in `hatch run test` command (#954)
271
298
 
299
+ ### 🧹 Chores
300
+
301
+ - PgVector - remove legacy filter support (#1068)
302
+
303
+ ### 🌀 Miscellaneous
304
+
305
+ - Chore: Update pgvector test for the new `apply_filter_policy` usage (#970)
306
+ - Chore: pgvector ruff update, don't ruff tests (#984)
307
+
308
+ ## [integrations/pgvector-v0.5.1] - 2024-07-17
309
+
310
+ ### 🐛 Bug Fixes
311
+
312
+ - `PgVector` - Fallback to default filter policy when deserializing retrievers without the init parameter (#900)
313
+
314
+ ## [integrations/pgvector-v0.5.0] - 2024-07-15
315
+
316
+ ### 🚀 Features
317
+
318
+ - Add filter_policy to pgvector integration (#820)
319
+
272
320
  ### ⚙️ CI
273
321
 
274
322
  - Retry tests to reduce flakyness (#836)
275
- - Adopt uv as installer (#1142)
276
323
 
277
324
  ### 🧹 Chores
278
325
 
279
326
  - Update ruff invocation to include check parameter (#853)
280
- - PgVector - remove legacy filter support (#1068)
281
- - Update changelog after removing legacy filters (#1083)
282
- - Update ruff linting scripts and settings (#1105)
283
327
 
284
328
  ### 🌀 Miscellaneous
285
329
 
286
330
  - Ci: install `pytest-rerunfailures` where needed; add retry config to `test-cov` script (#845)
287
331
  - Chore: Minor retriever pydoc fix (#884)
288
- - Chore: Update pgvector test for the new `apply_filter_policy` usage (#970)
289
- - Chore: pgvector ruff update, don't ruff tests (#984)
290
332
 
291
333
  ## [integrations/pgvector-v0.4.0] - 2024-06-20
292
334
 
293
335
  ### 🚀 Features
294
336
 
295
- - Defer the database connection to when it's needed (#773)
296
337
  - Add customizable index names for pgvector (#818)
297
338
 
339
+
340
+ ## [integrations/pgvector-v0.3.0] - 2024-05-30
341
+
342
+ ### 🚀 Features
343
+
344
+ - Defer the database connection to when it's needed (#773)
345
+
298
346
  ### 🌀 Miscellaneous
299
347
 
300
348
  - Docs: add missing api references (#728)
@@ -328,6 +376,14 @@
328
376
 
329
377
  ## [integrations/pgvector-v0.1.0] - 2024-02-14
330
378
 
379
+ ### 🌀 Miscellaneous
380
+
381
+ - Pgvector: generate API docs (#325)
382
+ - Pgvector: add an example (#334)
383
+ - Adopt `Secret` to pgvector (#402)
384
+
385
+ ## [integrations/pgvector-v0.0.1] - 2024-02-02
386
+
331
387
  ### 🐛 Bug Fixes
332
388
 
333
389
  - Pgvector: fix linting (#328)
@@ -338,8 +394,5 @@
338
394
  - Pgvector - filters (#257)
339
395
  - Pgvector - embedding retrieval (#298)
340
396
  - Pgvector - Embedding Retriever (#320)
341
- - Pgvector: generate API docs (#325)
342
- - Pgvector: add an example (#334)
343
- - Adopt `Secret` to pgvector (#402)
344
397
 
345
398
  <!-- generated by git-cliff -->
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pgvector-haystack
3
- Version: 6.6.0
3
+ Version: 6.6.1
4
4
  Summary: An integration of pgvector (vector search extension for Postgres) with Haystack
5
5
  Project-URL: Source, https://github.com/deepset-ai/haystack-core-integrations
6
6
  Project-URL: Documentation, https://github.com/deepset-ai/haystack-core-integrations/blob/main/integrations/pgvector/README.md
@@ -923,7 +923,7 @@ class PgvectorDocumentStore:
923
923
  )
924
924
  raise DocumentStoreError(error_msg) from e
925
925
 
926
- # get the number of the inserted documents, inspired by psycopg3 docs
926
+ # executemany(returning=True) yields one result set per document, so walk them all with nextset()
927
927
  # https://www.psycopg.org/psycopg3/docs/api/cursors.html#psycopg.Cursor.executemany
928
928
  written_docs = 0
929
929
  while True:
@@ -980,9 +980,14 @@ class PgvectorDocumentStore:
980
980
  )
981
981
  raise DocumentStoreError(error_msg) from e
982
982
 
983
+ # executemany(returning=True) yields one result set per document, so walk them all with nextset()
984
+ # https://www.psycopg.org/psycopg3/docs/api/cursors.html#psycopg.Cursor.executemany
983
985
  written_docs = 0
984
- async for _ in self._async_cursor:
985
- written_docs += 1
986
+ while True:
987
+ if await self._async_cursor.fetchone():
988
+ written_docs += 1
989
+ if not self._async_cursor.nextset():
990
+ break
986
991
 
987
992
  return written_docs
988
993
 
@@ -71,6 +71,10 @@ def _parse_logical_condition(condition: dict[str, Any]) -> tuple[Composed, list[
71
71
  msg = f"Unknown logical operator '{operator}'. Valid operators are: 'AND', 'OR'"
72
72
  raise FilterError(msg)
73
73
 
74
+ if not condition["conditions"]:
75
+ msg = f"'conditions' must not be empty in {condition}"
76
+ raise FilterError(msg)
77
+
74
78
  # logical conditions can be nested, so we need to parse them recursively
75
79
  conditions = []
76
80
  for c in condition["conditions"]:
@@ -66,6 +66,20 @@ class TestDocumentStore(
66
66
  with pytest.raises(DuplicateDocumentError):
67
67
  document_store.write_documents(docs, DuplicatePolicy.FAIL)
68
68
 
69
+ def test_write_documents_counts_every_document(self, document_store: PgvectorDocumentStore):
70
+ docs = [Document(id="1"), Document(id="2"), Document(id="3")]
71
+ assert document_store.write_documents(docs) == 3
72
+
73
+ def test_write_documents_skip_counts_only_new_documents(self, document_store: PgvectorDocumentStore):
74
+ document_store.write_documents([Document(id="1")])
75
+ docs = [Document(id="1"), Document(id="2"), Document(id="3")]
76
+ assert document_store.write_documents(docs, DuplicatePolicy.SKIP) == 2
77
+
78
+ def test_write_documents_overwrite_counts_every_document(self, document_store: PgvectorDocumentStore):
79
+ document_store.write_documents([Document(id="1", content="old")])
80
+ docs = [Document(id="1", content="new"), Document(id="2"), Document(id="3")]
81
+ assert document_store.write_documents(docs, DuplicatePolicy.OVERWRITE) == 3
82
+
69
83
  def test_get_metadata_field_unique_values_distinct_types(self, document_store: PgvectorDocumentStore):
70
84
  """
71
85
  Override: the base mixin test stores int, float, str and bool under the *same* metadata field
@@ -71,6 +71,20 @@ class TestDocumentStoreAsync(
71
71
  with pytest.raises(DuplicateDocumentError):
72
72
  await document_store.write_documents_async(docs, DuplicatePolicy.FAIL)
73
73
 
74
+ async def test_write_documents_async_counts_every_document(self, document_store: PgvectorDocumentStore):
75
+ docs = [Document(id="1"), Document(id="2"), Document(id="3")]
76
+ assert await document_store.write_documents_async(docs) == 3
77
+
78
+ async def test_write_documents_async_skip_counts_only_new_documents(self, document_store: PgvectorDocumentStore):
79
+ await document_store.write_documents_async([Document(id="1")])
80
+ docs = [Document(id="1"), Document(id="2"), Document(id="3")]
81
+ assert await document_store.write_documents_async(docs, DuplicatePolicy.SKIP) == 2
82
+
83
+ async def test_write_documents_async_overwrite_counts_every_document(self, document_store: PgvectorDocumentStore):
84
+ await document_store.write_documents_async([Document(id="1", content="old")])
85
+ docs = [Document(id="1", content="new"), Document(id="2"), Document(id="3")]
86
+ assert await document_store.write_documents_async(docs, DuplicatePolicy.OVERWRITE) == 3
87
+
74
88
  async def test_get_metadata_field_unique_values_distinct_types_async(self, document_store: PgvectorDocumentStore):
75
89
  """
76
90
  Override: the base mixin test stores int, float, str and bool under the *same* metadata field
@@ -483,3 +483,21 @@ def test_validate_filters():
483
483
  invalid_filters = {"field": "meta.number", "value": "100"}
484
484
  with pytest.raises(ValueError):
485
485
  _validate_filters(invalid_filters)
486
+
487
+
488
+ @pytest.mark.parametrize("operator", ["AND", "OR"])
489
+ def test_logical_condition_empty_conditions_raises(operator):
490
+ with pytest.raises(FilterError):
491
+ _parse_logical_condition({"operator": operator, "conditions": []})
492
+
493
+
494
+ def test_logical_condition_nested_empty_conditions_raises():
495
+ filters = {
496
+ "operator": "AND",
497
+ "conditions": [
498
+ {"field": "meta.type", "operator": "==", "value": "article"},
499
+ {"operator": "OR", "conditions": []},
500
+ ],
501
+ }
502
+ with pytest.raises(FilterError):
503
+ _convert_filters_to_where_clause_and_params(filters)