Skip to content

Commit 1556e6e

Browse files
test: add schemaless nested object attribute queries
1 parent 2aadc20 commit 1556e6e

1 file changed

Lines changed: 125 additions & 0 deletions

File tree

tests/e2e/Adapter/Scopes/SchemalessTests.php

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,4 +1685,129 @@ public function testElemMatchComplex(): void
16851685
// Clean up
16861686
$database->deleteCollection($collectionId);
16871687
}
1688+
1689+
public function testSchemalessNestedObjectAttributeQueries(): void
1690+
{
1691+
/** @var Database $database */
1692+
$database = static::getDatabase();
1693+
1694+
// Only run for schemaless adapters that support object attributes
1695+
if ($database->getAdapter()->getSupportForAttributes() || !$database->getAdapter()->getSupportForObject()) {
1696+
$this->expectNotToPerformAssertions();
1697+
return;
1698+
}
1699+
1700+
$col = uniqid('sl_nested_obj');
1701+
$database->createCollection($col);
1702+
1703+
$permissions = [
1704+
Permission::read(Role::any()),
1705+
Permission::write(Role::any()),
1706+
Permission::update(Role::any()),
1707+
Permission::delete(Role::any())
1708+
];
1709+
1710+
// Documents with nested objects
1711+
$database->createDocument($col, new Document([
1712+
'$id' => 'u1',
1713+
'$permissions' => $permissions,
1714+
'profile' => [
1715+
'name' => 'Alice',
1716+
'location' => [
1717+
'country' => 'US',
1718+
'city' => 'New York',
1719+
'coordinates' => [
1720+
'lat' => 40.7128,
1721+
'lng' => -74.0060,
1722+
],
1723+
],
1724+
],
1725+
]));
1726+
1727+
$database->createDocument($col, new Document([
1728+
'$id' => 'u2',
1729+
'$permissions' => $permissions,
1730+
'profile' => [
1731+
'name' => 'Bob',
1732+
'location' => [
1733+
'country' => 'UK',
1734+
'city' => 'London',
1735+
'coordinates' => [
1736+
'lat' => 51.5074,
1737+
'lng' => -0.1278,
1738+
],
1739+
],
1740+
],
1741+
]));
1742+
1743+
// Document without full nesting
1744+
$database->createDocument($col, new Document([
1745+
'$id' => 'u3',
1746+
'$permissions' => $permissions,
1747+
'profile' => [
1748+
'name' => 'Charlie',
1749+
'location' => [
1750+
'country' => 'US',
1751+
],
1752+
],
1753+
]));
1754+
1755+
// Query using Mongo-style dotted paths: attribute.key.key
1756+
$nycDocs = $database->find($col, [
1757+
Query::equal('profile.location.city', ['New York']),
1758+
]);
1759+
$this->assertCount(1, $nycDocs);
1760+
$this->assertEquals('u1', $nycDocs[0]->getId());
1761+
1762+
// Query on deeper nested numeric field
1763+
$northOf50 = $database->find($col, [
1764+
Query::greaterThan('profile.location.coordinates.lat', 50),
1765+
]);
1766+
$this->assertCount(1, $northOf50);
1767+
$this->assertEquals('u2', $northOf50[0]->getId());
1768+
1769+
// exists on nested key should match docs where the full path exists
1770+
$withCoordinates = $database->find($col, [
1771+
Query::exists(['profile.location.coordinates.lng']),
1772+
]);
1773+
$this->assertCount(2, $withCoordinates);
1774+
$ids = array_map(fn (Document $doc) => $doc->getId(), $withCoordinates);
1775+
$this->assertContains('u1', $ids);
1776+
$this->assertContains('u2', $ids);
1777+
$this->assertNotContains('u3', $ids);
1778+
1779+
// Combination of filters on nested paths
1780+
$usWithCoords = $database->find($col, [
1781+
Query::equal('profile.location.country', ['US']),
1782+
Query::exists(['profile.location.coordinates.lat']),
1783+
]);
1784+
$this->assertCount(1, $usWithCoords);
1785+
$this->assertEquals('u1', $usWithCoords[0]->getId());
1786+
1787+
// contains on object attribute using nested structure: parent.key and [key => [key => 'value']]
1788+
$matchedByNestedContains = $database->find($col, [
1789+
Query::contains('profile', [
1790+
'location' => [
1791+
'city' => 'London',
1792+
],
1793+
]),
1794+
]);
1795+
$this->assertCount(1, $matchedByNestedContains);
1796+
$this->assertEquals('u2', $matchedByNestedContains[0]->getId());
1797+
1798+
// equal on object attribute using nested structure should behave similarly
1799+
$matchedByNestedEqual = $database->find($col, [
1800+
Query::equal('profile', [
1801+
'location' => [
1802+
'country' => 'US',
1803+
],
1804+
]),
1805+
]);
1806+
$this->assertCount(2, $matchedByNestedEqual);
1807+
$idsEqual = array_map(fn (Document $doc) => $doc->getId(), $matchedByNestedEqual);
1808+
$this->assertContains('u1', $idsEqual);
1809+
$this->assertContains('u3', $idsEqual);
1810+
1811+
$database->deleteCollection($col);
1812+
}
16881813
}

0 commit comments

Comments
 (0)