Skip to content

Commit ed00131

Browse files
committed
Add first tests
1 parent 333c7dc commit ed00131

File tree

7 files changed

+169
-1
lines changed

7 files changed

+169
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.idea/
22
.DS_STORE
3+
__pycache__/

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ ______________________________________________________________________
44

55
## Changes in version 0.1 (2025/09/XX)
66

7-
- Initial release.
7+
- Initial release.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from ._version import __version__
2+
from .index import (
3+
create_fulltext_search_index,
4+
create_vector_search_index,
5+
drop_vector_search_index,
6+
update_vector_search_index,
7+
)
8+
from .pipeline import (
9+
combine_pipelines,
10+
final_hybrid_stage,
11+
reciprocal_rank_stage,
12+
text_search_stage,
13+
vector_search_stage,
14+
)
15+
16+
__all__ = [
17+
"__version__",
18+
"create_vector_search_index",
19+
"drop_vector_search_index",
20+
"update_vector_search_index",
21+
"create_fulltext_search_index",
22+
"text_search_stage",
23+
"vector_search_stage",
24+
"combine_pipelines",
25+
"reciprocal_rank_stage",
26+
"final_hybrid_stage",
27+
]

pymongo_vectorsearch_utils/index.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,31 @@ def update_vector_search_index(
186186
logger.info("Update succeeded")
187187

188188

189+
def drop_vector_search_index(
190+
collection: Collection[Any],
191+
index_name: str,
192+
*,
193+
wait_until_complete: float | None = None,
194+
) -> None:
195+
"""Drop a created vector search index.
196+
197+
Args:
198+
collection (Collection): MongoDB Collection with index to be dropped.
199+
index_name (str): Name of the MongoDB index.
200+
wait_until_complete (Optional[float]): If provided, number of seconds to wait
201+
until search index is ready.
202+
"""
203+
logger.info("Dropping Search Index %s from Collection: %s", index_name, collection.name)
204+
collection.drop_search_index(index_name)
205+
if wait_until_complete:
206+
wait_for_predicate(
207+
predicate=lambda: len(list(collection.list_search_indexes())) == 0,
208+
err=f"Index {index_name} did not drop in {wait_until_complete}!",
209+
timeout=wait_until_complete,
210+
)
211+
logger.info("Vector Search index %s.%s dropped", collection.name, index_name)
212+
213+
189214
def create_fulltext_search_index(
190215
collection: Collection[Any],
191216
index_name: str,

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ testpaths = [
6262
python_version = "3.10"
6363
strict = true
6464
enable_error_code = ["ignore-without-code", "redundant-expr", "truthy-bool"]
65+
exclude = ["tests/"]
6566

6667
[tool.ruff]
6768
line-length = 100

tests/__init__.py

Whitespace-only changes.

tests/test_index.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import os
2+
from collections.abc import Generator
3+
4+
import pytest
5+
from pymongo import MongoClient
6+
from pymongo.collection import Collection
7+
8+
from pymongo_vectorsearch_utils.index import (
9+
create_vector_search_index,
10+
drop_vector_search_index,
11+
is_index_ready,
12+
update_vector_search_index,
13+
)
14+
15+
DB_NAME = "vectorsearch_utils_test"
16+
COLLECTION_NAME = "test_index"
17+
VECTOR_INDEX_NAME = "vector_index"
18+
19+
TIMEOUT = 120
20+
DIMENSIONS = 10
21+
22+
23+
@pytest.fixture(scope="module")
24+
def client() -> Generator[MongoClient, None, None]:
25+
conn_str = os.environ.get("MONGODB_URI", "mongodb://127.0.0.1:27017?directConnection=true")
26+
client = MongoClient(conn_str)
27+
yield client
28+
client.close()
29+
30+
31+
@pytest.fixture
32+
def collection(client) -> Generator:
33+
if COLLECTION_NAME not in client[DB_NAME].list_collection_names():
34+
clxn = client[DB_NAME].create_collection(COLLECTION_NAME)
35+
else:
36+
clxn = client[DB_NAME][COLLECTION_NAME]
37+
clxn = client[DB_NAME][COLLECTION_NAME]
38+
clxn.delete_many({})
39+
yield clxn
40+
clxn.delete_many({})
41+
42+
43+
def test_search_index_create_and_drop(collection: Collection) -> None:
44+
index_name = VECTOR_INDEX_NAME
45+
dimensions = DIMENSIONS
46+
path = "embedding"
47+
similarity = "cosine"
48+
filters: list[str] | None = None
49+
wait_until_complete = TIMEOUT
50+
51+
for index_info in collection.list_search_indexes():
52+
drop_vector_search_index(
53+
collection, index_info["name"], wait_until_complete=wait_until_complete
54+
)
55+
56+
assert len(list(collection.list_search_indexes())) == 0
57+
58+
create_vector_search_index(
59+
collection=collection,
60+
index_name=index_name,
61+
dimensions=dimensions,
62+
path=path,
63+
similarity=similarity,
64+
filters=filters,
65+
wait_until_complete=wait_until_complete,
66+
)
67+
68+
assert is_index_ready(collection, index_name)
69+
indexes = list(collection.list_search_indexes())
70+
assert len(indexes) == 1
71+
assert indexes[0]["name"] == index_name
72+
73+
drop_vector_search_index(collection, index_name, wait_until_complete=wait_until_complete)
74+
75+
indexes = list(collection.list_search_indexes())
76+
assert len(indexes) == 0
77+
78+
79+
def test_search_index_update_vector_search_index(collection: Collection) -> None:
80+
index_name = "INDEX_TO_UPDATE"
81+
similarity_orig = "cosine"
82+
similarity_new = "euclidean"
83+
84+
# Create another index
85+
create_vector_search_index(
86+
collection=collection,
87+
index_name=index_name,
88+
dimensions=DIMENSIONS,
89+
path="embedding",
90+
similarity=similarity_orig,
91+
wait_until_complete=TIMEOUT,
92+
)
93+
94+
assert is_index_ready(collection, index_name)
95+
indexes = list(collection.list_search_indexes())
96+
assert len(indexes) == 1
97+
assert indexes[0]["name"] == index_name
98+
assert indexes[0]["latestDefinition"]["fields"][0]["similarity"] == similarity_orig
99+
100+
# Update the index and test new similarity
101+
update_vector_search_index(
102+
collection=collection,
103+
index_name=index_name,
104+
dimensions=DIMENSIONS,
105+
path="embedding",
106+
similarity=similarity_new,
107+
wait_until_complete=TIMEOUT,
108+
)
109+
110+
assert is_index_ready(collection, index_name)
111+
indexes = list(collection.list_search_indexes())
112+
assert len(indexes) == 1
113+
assert indexes[0]["name"] == index_name
114+
assert indexes[0]["latestDefinition"]["fields"][0]["similarity"] == similarity_new

0 commit comments

Comments
 (0)