@@ -1155,4 +1155,131 @@ public function testSchemalessDates(): void
11551155
11561156 $ database ->deleteCollection ($ col );
11571157 }
1158+
1159+ public function testSchemalessExists (): void
1160+ {
1161+ /** @var Database $database */
1162+ $ database = static ::getDatabase ();
1163+
1164+ if ($ database ->getAdapter ()->getSupportForAttributes ()) {
1165+ $ this ->expectNotToPerformAssertions ();
1166+ return ;
1167+ }
1168+
1169+ $ colName = uniqid ('schemaless_exists ' );
1170+ $ database ->createCollection ($ colName );
1171+
1172+ $ permissions = [
1173+ Permission::read (Role::any ()),
1174+ Permission::write (Role::any ()),
1175+ Permission::update (Role::any ()),
1176+ Permission::delete (Role::any ())
1177+ ];
1178+
1179+ // Create documents with and without the 'optionalField' attribute
1180+ $ docs = [
1181+ new Document (['$id ' => 'doc1 ' , '$permissions ' => $ permissions , 'optionalField ' => 'value1 ' , 'name ' => 'doc1 ' ]),
1182+ new Document (['$id ' => 'doc2 ' , '$permissions ' => $ permissions , 'optionalField ' => 'value2 ' , 'name ' => 'doc2 ' ]),
1183+ new Document (['$id ' => 'doc3 ' , '$permissions ' => $ permissions , 'name ' => 'doc3 ' ]), // no optionalField
1184+ new Document (['$id ' => 'doc4 ' , '$permissions ' => $ permissions , 'optionalField ' => null , 'name ' => 'doc4 ' ]), // exists but null
1185+ new Document (['$id ' => 'doc5 ' , '$permissions ' => $ permissions , 'name ' => 'doc5 ' ]), // no optionalField
1186+ ];
1187+ $ this ->assertEquals (5 , $ database ->createDocuments ($ colName , $ docs ));
1188+
1189+ // Test exists - should return documents where optionalField exists (even if null)
1190+ $ documents = $ database ->find ($ colName , [
1191+ Query::exists ('optionalField ' ),
1192+ ]);
1193+
1194+ $ this ->assertEquals (3 , count ($ documents )); // doc1, doc2, doc4
1195+ $ ids = array_map (fn ($ doc ) => $ doc ->getId (), $ documents );
1196+ $ this ->assertContains ('doc1 ' , $ ids );
1197+ $ this ->assertContains ('doc2 ' , $ ids );
1198+ $ this ->assertContains ('doc4 ' , $ ids );
1199+
1200+ // Verify that doc4 is included even though optionalField is null
1201+ $ doc4 = array_filter ($ documents , fn ($ doc ) => $ doc ->getId () === 'doc4 ' );
1202+ $ this ->assertCount (1 , $ doc4 );
1203+ $ doc4Array = array_values ($ doc4 );
1204+ $ this ->assertTrue (array_key_exists ('optionalField ' , $ doc4Array [0 ]->getAttributes ()));
1205+
1206+ // Test exists with another attribute
1207+ $ documents = $ database ->find ($ colName , [
1208+ Query::exists ('name ' ),
1209+ ]);
1210+ $ this ->assertEquals (5 , count ($ documents )); // All documents have 'name'
1211+
1212+ // Test exists with non-existent attribute
1213+ $ documents = $ database ->find ($ colName , [
1214+ Query::exists ('nonExistentField ' ),
1215+ ]);
1216+ $ this ->assertEquals (0 , count ($ documents ));
1217+
1218+ $ database ->deleteCollection ($ colName );
1219+ }
1220+
1221+ public function testSchemalessNotExists (): void
1222+ {
1223+ /** @var Database $database */
1224+ $ database = static ::getDatabase ();
1225+
1226+ if ($ database ->getAdapter ()->getSupportForAttributes ()) {
1227+ $ this ->expectNotToPerformAssertions ();
1228+ return ;
1229+ }
1230+
1231+ $ colName = uniqid ('schemaless_not_exists ' );
1232+ $ database ->createCollection ($ colName );
1233+
1234+ $ permissions = [
1235+ Permission::read (Role::any ()),
1236+ Permission::write (Role::any ()),
1237+ Permission::update (Role::any ()),
1238+ Permission::delete (Role::any ())
1239+ ];
1240+
1241+ // Create documents with and without the 'optionalField' attribute
1242+ $ docs = [
1243+ new Document (['$id ' => 'doc1 ' , '$permissions ' => $ permissions , 'optionalField ' => 'value1 ' , 'name ' => 'doc1 ' ]),
1244+ new Document (['$id ' => 'doc2 ' , '$permissions ' => $ permissions , 'optionalField ' => 'value2 ' , 'name ' => 'doc2 ' ]),
1245+ new Document (['$id ' => 'doc3 ' , '$permissions ' => $ permissions , 'name ' => 'doc3 ' ]), // no optionalField
1246+ new Document (['$id ' => 'doc4 ' , '$permissions ' => $ permissions , 'optionalField ' => null , 'name ' => 'doc4 ' ]), // exists but null
1247+ new Document (['$id ' => 'doc5 ' , '$permissions ' => $ permissions , 'name ' => 'doc5 ' ]), // no optionalField
1248+ ];
1249+ $ this ->assertEquals (5 , $ database ->createDocuments ($ colName , $ docs ));
1250+
1251+ // Test notExists - should return documents where optionalField does not exist
1252+ $ documents = $ database ->find ($ colName , [
1253+ Query::notExists ('optionalField ' ),
1254+ ]);
1255+
1256+ $ this ->assertEquals (2 , count ($ documents )); // doc3, doc5
1257+ $ ids = array_map (fn ($ doc ) => $ doc ->getId (), $ documents );
1258+ $ this ->assertContains ('doc3 ' , $ ids );
1259+ $ this ->assertContains ('doc5 ' , $ ids );
1260+
1261+ // Verify that doc4 is NOT included (it exists even though null)
1262+ $ this ->assertNotContains ('doc4 ' , $ ids );
1263+
1264+ // Test notExists with another attribute
1265+ $ documents = $ database ->find ($ colName , [
1266+ Query::notExists ('name ' ),
1267+ ]);
1268+ $ this ->assertEquals (0 , count ($ documents )); // All documents have 'name'
1269+
1270+ // Test notExists with non-existent attribute
1271+ $ documents = $ database ->find ($ colName , [
1272+ Query::notExists ('nonExistentField ' ),
1273+ ]);
1274+ $ this ->assertEquals (5 , count ($ documents )); // All documents don't have this field
1275+
1276+ // Test combination of exists and notExists
1277+ $ documents = $ database ->find ($ colName , [
1278+ Query::exists ('name ' ),
1279+ Query::notExists ('optionalField ' ),
1280+ ]);
1281+ $ this ->assertEquals (2 , count ($ documents )); // doc3, doc5
1282+
1283+ $ database ->deleteCollection ($ colName );
1284+ }
11581285}
0 commit comments