@@ -930,6 +930,43 @@ def test_update_by_filter_advanced_filters(document_store: DocumentStore):
930930 assert len (featured_docs ) == 2
931931
932932
933+ class UpdateByFilterAsyncTest :
934+ """
935+ Tests for Document Store update_by_filter_async().
936+
937+ Only mix in for stores that implement update_by_filter_async.
938+ """
939+
940+ @staticmethod
941+ @pytest .mark .asyncio
942+ async def test_update_by_filter_async (document_store : DocumentStore , filterable_docs : list [Document ]):
943+ """Update documents matching a filter asynchronously and verify count and meta changes."""
944+ document_store .write_documents (filterable_docs )
945+ expected_count = len ([d for d in filterable_docs if d .meta .get ("chapter" ) == "intro" ])
946+ assert document_store .count_documents () == len (filterable_docs )
947+
948+ sig = inspect .signature (document_store .update_by_filter_async ) # type:ignore[attr-defined]
949+ params = {"refresh" : True } if "refresh" in sig .parameters else {}
950+ updated_count = await document_store .update_by_filter_async ( # type:ignore[attr-defined]
951+ filters = {"field" : "meta.chapter" , "operator" : "==" , "value" : "intro" }, meta = {"updated" : True }, ** params
952+ )
953+ assert updated_count == expected_count
954+
955+ updated_docs = document_store .filter_documents (
956+ filters = {"field" : "meta.updated" , "operator" : "==" , "value" : True }
957+ )
958+ assert len (updated_docs ) == expected_count
959+ for doc in updated_docs :
960+ assert doc .meta ["chapter" ] == "intro"
961+ assert doc .meta ["updated" ] is True
962+
963+ not_updated_docs = document_store .filter_documents (
964+ filters = {"field" : "meta.chapter" , "operator" : "==" , "value" : "abstract" }
965+ )
966+ for doc in not_updated_docs :
967+ assert doc .meta .get ("updated" ) is not True
968+
969+
933970class CountDocumentsByFilterTest :
934971 """
935972 Tests for Document Store count_documents_by_filter().
@@ -1005,6 +1042,85 @@ def test_count_documents_by_filter_empty_collection(document_store: DocumentStor
10051042 assert count == 0
10061043
10071044
1045+ class CountDocumentsByFilterAsyncTest :
1046+ """
1047+ Tests for Document Store count_documents_by_filter_async().
1048+
1049+ Only mix in for stores that implement count_documents_by_filter_async.
1050+ """
1051+
1052+ @staticmethod
1053+ @pytest .mark .asyncio
1054+ async def test_count_documents_by_filter_async_simple (document_store : DocumentStore ):
1055+ """Test count_documents_by_filter_async() with a simple equality filter."""
1056+ docs = [
1057+ Document (content = "Doc 1" , meta = {"category" : "A" , "status" : "active" }),
1058+ Document (content = "Doc 2" , meta = {"category" : "B" , "status" : "active" }),
1059+ Document (content = "Doc 3" , meta = {"category" : "A" , "status" : "inactive" }),
1060+ Document (content = "Doc 4" , meta = {"category" : "A" , "status" : "active" }),
1061+ ]
1062+ document_store .write_documents (docs )
1063+ assert document_store .count_documents () == 4
1064+
1065+ count = await document_store .count_documents_by_filter_async ( # type:ignore[attr-defined]
1066+ filters = {"field" : "meta.category" , "operator" : "==" , "value" : "A" }
1067+ )
1068+ assert count == 3
1069+
1070+ count = await document_store .count_documents_by_filter_async ( # type:ignore[attr-defined]
1071+ filters = {"field" : "meta.category" , "operator" : "==" , "value" : "B" }
1072+ )
1073+ assert count == 1
1074+
1075+ @staticmethod
1076+ @pytest .mark .asyncio
1077+ async def test_count_documents_by_filter_async_compound (document_store : DocumentStore ):
1078+ """Test count_documents_by_filter_async() with AND filter."""
1079+ docs = [
1080+ Document (content = "Doc 1" , meta = {"category" : "A" , "status" : "active" }),
1081+ Document (content = "Doc 2" , meta = {"category" : "B" , "status" : "active" }),
1082+ Document (content = "Doc 3" , meta = {"category" : "A" , "status" : "inactive" }),
1083+ Document (content = "Doc 4" , meta = {"category" : "A" , "status" : "active" }),
1084+ ]
1085+ document_store .write_documents (docs )
1086+ assert document_store .count_documents () == 4
1087+
1088+ count = await document_store .count_documents_by_filter_async ( # type:ignore[attr-defined]
1089+ filters = {
1090+ "operator" : "AND" ,
1091+ "conditions" : [
1092+ {"field" : "meta.category" , "operator" : "==" , "value" : "A" },
1093+ {"field" : "meta.status" , "operator" : "==" , "value" : "active" },
1094+ ],
1095+ }
1096+ )
1097+ assert count == 2
1098+
1099+ @staticmethod
1100+ @pytest .mark .asyncio
1101+ async def test_count_documents_by_filter_async_no_matches (document_store : DocumentStore ):
1102+ """Test count_documents_by_filter_async() when filter matches no documents."""
1103+ docs = [Document (content = "Doc 1" , meta = {"category" : "A" }), Document (content = "Doc 2" , meta = {"category" : "B" })]
1104+ document_store .write_documents (docs )
1105+ assert document_store .count_documents () == 2
1106+
1107+ count = await document_store .count_documents_by_filter_async ( # type:ignore[attr-defined]
1108+ filters = {"field" : "meta.category" , "operator" : "==" , "value" : "Z" }
1109+ )
1110+ assert count == 0
1111+
1112+ @staticmethod
1113+ @pytest .mark .asyncio
1114+ async def test_count_documents_by_filter_async_empty_collection (document_store : DocumentStore ):
1115+ """Test count_documents_by_filter_async() on an empty store."""
1116+ assert document_store .count_documents () == 0
1117+
1118+ count = await document_store .count_documents_by_filter_async ( # type:ignore[attr-defined]
1119+ filters = {"field" : "meta.category" , "operator" : "==" , "value" : "A" }
1120+ )
1121+ assert count == 0
1122+
1123+
10081124class CountUniqueMetadataByFilterTest :
10091125 """
10101126 Tests for Document Store count_unique_metadata_by_filter().
@@ -1072,6 +1188,78 @@ def test_count_unique_metadata_by_filter_with_multiple_filters(document_store: D
10721188 assert count == 1
10731189
10741190
1191+ class CountUniqueMetadataByFilterAsyncTest :
1192+ """
1193+ Tests for Document Store count_unique_metadata_by_filter_async().
1194+
1195+ Only mix in for stores that implement count_unique_metadata_by_filter_async.
1196+ """
1197+
1198+ @staticmethod
1199+ @pytest .mark .asyncio
1200+ async def test_count_unique_metadata_by_filter_async_all_documents (document_store : DocumentStore ):
1201+ """Test count_unique_metadata_by_filter_async() with no filter returns distinct counts for all docs."""
1202+ docs = [
1203+ Document (content = "Doc 1" , meta = {"category" : "A" , "status" : "active" , "priority" : 1 }),
1204+ Document (content = "Doc 2" , meta = {"category" : "B" , "status" : "active" , "priority" : 2 }),
1205+ Document (content = "Doc 3" , meta = {"category" : "A" , "status" : "inactive" , "priority" : 1 }),
1206+ Document (content = "Doc 4" , meta = {"category" : "A" , "status" : "active" , "priority" : 3 }),
1207+ Document (content = "Doc 5" , meta = {"category" : "C" , "status" : "active" , "priority" : 2 }),
1208+ ]
1209+ document_store .write_documents (docs )
1210+ assert document_store .count_documents () == 5
1211+
1212+ counts = await document_store .count_unique_metadata_by_filter_async ( # type:ignore[attr-defined]
1213+ filters = {}, metadata_fields = ["category" , "status" , "priority" ]
1214+ )
1215+ assert counts ["category" ] == 3
1216+ assert counts ["status" ] == 2
1217+ assert counts ["priority" ] == 3
1218+
1219+ @staticmethod
1220+ @pytest .mark .asyncio
1221+ async def test_count_unique_metadata_by_filter_async_with_filter (document_store : DocumentStore ):
1222+ """Test count_unique_metadata_by_filter_async() with a filter."""
1223+ docs = [
1224+ Document (content = "Doc 1" , meta = {"category" : "A" , "status" : "active" , "priority" : 1 }),
1225+ Document (content = "Doc 2" , meta = {"category" : "B" , "status" : "active" , "priority" : 2 }),
1226+ Document (content = "Doc 3" , meta = {"category" : "A" , "status" : "inactive" , "priority" : 1 }),
1227+ Document (content = "Doc 4" , meta = {"category" : "A" , "status" : "active" , "priority" : 3 }),
1228+ ]
1229+ document_store .write_documents (docs )
1230+ assert document_store .count_documents () == 4
1231+
1232+ counts = await document_store .count_unique_metadata_by_filter_async ( # type:ignore[attr-defined]
1233+ filters = {"field" : "meta.category" , "operator" : "==" , "value" : "A" }, metadata_fields = ["status" , "priority" ]
1234+ )
1235+ assert counts ["status" ] == 2
1236+ assert counts ["priority" ] == 2
1237+
1238+ @staticmethod
1239+ @pytest .mark .asyncio
1240+ async def test_count_unique_metadata_by_filter_async_with_multiple_filters (document_store : DocumentStore ):
1241+ """Test counting unique metadata asynchronously with multiple filters."""
1242+ docs = [
1243+ Document (content = "Doc 1" , meta = {"category" : "A" , "year" : 2023 }),
1244+ Document (content = "Doc 2" , meta = {"category" : "A" , "year" : 2024 }),
1245+ Document (content = "Doc 3" , meta = {"category" : "B" , "year" : 2023 }),
1246+ Document (content = "Doc 4" , meta = {"category" : "B" , "year" : 2024 }),
1247+ ]
1248+ document_store .write_documents (docs )
1249+
1250+ counts = await document_store .count_unique_metadata_by_filter_async ( # type:ignore[attr-defined]
1251+ filters = {
1252+ "operator" : "AND" ,
1253+ "conditions" : [
1254+ {"field" : "meta.category" , "operator" : "==" , "value" : "B" },
1255+ {"field" : "meta.year" , "operator" : "==" , "value" : 2023 },
1256+ ],
1257+ },
1258+ metadata_fields = ["category" , "year" ],
1259+ )
1260+ assert counts == {"category" : 1 , "year" : 1 }
1261+
1262+
10751263class GetMetadataFieldsInfoTest :
10761264 """
10771265 Tests for Document Store get_metadata_fields_info().
0 commit comments