@objectql/driver-mongo 1.7.2 → 1.7.3
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.
- package/CHANGELOG.md +8 -0
- package/LICENSE +118 -21
- package/dist/index.d.ts +9 -0
- package/dist/index.js +91 -57
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/index.ts +85 -48
- package/test/index.test.ts +100 -0
- package/test/integration.test.ts +62 -0
- package/tsconfig.tsbuildinfo +1 -1
package/test/index.test.ts
CHANGED
|
@@ -220,4 +220,104 @@ describe('MongoDriver', () => {
|
|
|
220
220
|
expect(results[0]).toEqual({ id: '456', name: 'Dave' });
|
|
221
221
|
});
|
|
222
222
|
|
|
223
|
+
it('should handle nested filter groups', async () => {
|
|
224
|
+
const query = {
|
|
225
|
+
filters: [
|
|
226
|
+
[
|
|
227
|
+
['status', '=', 'completed'],
|
|
228
|
+
'and',
|
|
229
|
+
['amount', '>', 100]
|
|
230
|
+
],
|
|
231
|
+
'or',
|
|
232
|
+
[
|
|
233
|
+
['customer', '=', 'Alice'],
|
|
234
|
+
'and',
|
|
235
|
+
['status', '=', 'pending']
|
|
236
|
+
]
|
|
237
|
+
]
|
|
238
|
+
};
|
|
239
|
+
await driver.find('orders', query);
|
|
240
|
+
|
|
241
|
+
// Expected MongoDB query structure:
|
|
242
|
+
// { $or: [
|
|
243
|
+
// { $and: [{ status: { $eq: 'completed' } }, { amount: { $gt: 100 } }] },
|
|
244
|
+
// { $and: [{ customer: { $eq: 'Alice' } }, { status: { $eq: 'pending' } }] }
|
|
245
|
+
// ] }
|
|
246
|
+
expect(mockCollection.find).toHaveBeenCalledWith(
|
|
247
|
+
{
|
|
248
|
+
$or: [
|
|
249
|
+
{ $and: [{ status: { $eq: 'completed' } }, { amount: { $gt: 100 } }] },
|
|
250
|
+
{ $and: [{ customer: { $eq: 'Alice' } }, { status: { $eq: 'pending' } }] }
|
|
251
|
+
]
|
|
252
|
+
},
|
|
253
|
+
expect.any(Object)
|
|
254
|
+
);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
it('should handle deeply nested filter groups', async () => {
|
|
258
|
+
const query = {
|
|
259
|
+
filters: [
|
|
260
|
+
[
|
|
261
|
+
[
|
|
262
|
+
['age', '>', 22],
|
|
263
|
+
'and',
|
|
264
|
+
['status', '=', 'active']
|
|
265
|
+
],
|
|
266
|
+
'or',
|
|
267
|
+
['role', '=', 'admin']
|
|
268
|
+
],
|
|
269
|
+
'and',
|
|
270
|
+
['name', '!=', 'Bob']
|
|
271
|
+
]
|
|
272
|
+
};
|
|
273
|
+
await driver.find('users', query);
|
|
274
|
+
|
|
275
|
+
// Expected structure:
|
|
276
|
+
// { $and: [
|
|
277
|
+
// { $or: [
|
|
278
|
+
// { $and: [{ age: { $gt: 22 } }, { status: { $eq: 'active' } }] },
|
|
279
|
+
// { role: { $eq: 'admin' } }
|
|
280
|
+
// ] },
|
|
281
|
+
// { name: { $ne: 'Bob' } }
|
|
282
|
+
// ] }
|
|
283
|
+
expect(mockCollection.find).toHaveBeenCalledWith(
|
|
284
|
+
{
|
|
285
|
+
$and: [
|
|
286
|
+
{
|
|
287
|
+
$or: [
|
|
288
|
+
{ $and: [{ age: { $gt: 22 } }, { status: { $eq: 'active' } }] },
|
|
289
|
+
{ role: { $eq: 'admin' } }
|
|
290
|
+
]
|
|
291
|
+
},
|
|
292
|
+
{ name: { $ne: 'Bob' } }
|
|
293
|
+
]
|
|
294
|
+
},
|
|
295
|
+
expect.any(Object)
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('should handle nested groups with implicit AND', async () => {
|
|
300
|
+
const query = {
|
|
301
|
+
filters: [
|
|
302
|
+
[
|
|
303
|
+
['status', '=', 'active'],
|
|
304
|
+
['role', '=', 'admin']
|
|
305
|
+
],
|
|
306
|
+
['age', '>', 25]
|
|
307
|
+
]
|
|
308
|
+
};
|
|
309
|
+
await driver.find('users', query);
|
|
310
|
+
|
|
311
|
+
// Nested array without explicit 'and' should still be treated as AND
|
|
312
|
+
expect(mockCollection.find).toHaveBeenCalledWith(
|
|
313
|
+
{
|
|
314
|
+
$and: [
|
|
315
|
+
{ $and: [{ status: { $eq: 'active' } }, { role: { $eq: 'admin' } }] },
|
|
316
|
+
{ age: { $gt: 25 } }
|
|
317
|
+
]
|
|
318
|
+
},
|
|
319
|
+
expect.any(Object)
|
|
320
|
+
);
|
|
321
|
+
});
|
|
322
|
+
|
|
223
323
|
});
|
package/test/integration.test.ts
CHANGED
|
@@ -539,6 +539,68 @@ describe('MongoDriver Integration Tests', () => {
|
|
|
539
539
|
expect(results.length).toBe(2);
|
|
540
540
|
});
|
|
541
541
|
|
|
542
|
+
test('should handle nested filter groups', async () => {
|
|
543
|
+
// Create test data matching the SQL driver's advanced test
|
|
544
|
+
await driver.create('orders', { customer: 'Alice', product: 'Laptop', amount: 1200.00, quantity: 1, status: 'completed' });
|
|
545
|
+
await driver.create('orders', { customer: 'Bob', product: 'Mouse', amount: 25.50, quantity: 2, status: 'completed' });
|
|
546
|
+
await driver.create('orders', { customer: 'Alice', product: 'Keyboard', amount: 75.00, quantity: 1, status: 'pending' });
|
|
547
|
+
await driver.create('orders', { customer: 'Charlie', product: 'Monitor', amount: 350.00, quantity: 1, status: 'completed' });
|
|
548
|
+
|
|
549
|
+
// Nested filter: (status = 'completed' AND amount > 100) OR (customer = 'Alice' AND status = 'pending')
|
|
550
|
+
const results = await driver.find('orders', {
|
|
551
|
+
filters: [
|
|
552
|
+
[
|
|
553
|
+
['status', '=', 'completed'],
|
|
554
|
+
'and',
|
|
555
|
+
['amount', '>', 100]
|
|
556
|
+
],
|
|
557
|
+
'or',
|
|
558
|
+
[
|
|
559
|
+
['customer', '=', 'Alice'],
|
|
560
|
+
'and',
|
|
561
|
+
['status', '=', 'pending']
|
|
562
|
+
]
|
|
563
|
+
]
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
// Should match: Alice's Laptop (completed, 1200), Charlie's Monitor (completed, 350), Alice's Keyboard (pending)
|
|
567
|
+
expect(results.length).toBe(3);
|
|
568
|
+
|
|
569
|
+
const customers = results.map(r => r.customer).sort();
|
|
570
|
+
expect(customers).toEqual(['Alice', 'Alice', 'Charlie']);
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
test('should handle deeply nested filters', async () => {
|
|
574
|
+
await driver.create('users', { name: 'Alice', age: 25, status: 'active', role: 'admin' });
|
|
575
|
+
await driver.create('users', { name: 'Bob', age: 30, status: 'active', role: 'user' });
|
|
576
|
+
await driver.create('users', { name: 'Charlie', age: 20, status: 'inactive', role: 'user' });
|
|
577
|
+
await driver.create('users', { name: 'Dave', age: 35, status: 'active', role: 'admin' });
|
|
578
|
+
|
|
579
|
+
// Complex nested: ((age > 22 AND status = 'active') OR role = 'admin') AND name != 'Bob'
|
|
580
|
+
const results = await driver.find('users', {
|
|
581
|
+
filters: [
|
|
582
|
+
[
|
|
583
|
+
[
|
|
584
|
+
['age', '>', 22],
|
|
585
|
+
'and',
|
|
586
|
+
['status', '=', 'active']
|
|
587
|
+
],
|
|
588
|
+
'or',
|
|
589
|
+
['role', '=', 'admin']
|
|
590
|
+
],
|
|
591
|
+
'and',
|
|
592
|
+
['name', '!=', 'Bob']
|
|
593
|
+
]
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
// Should match: Alice (age>22 AND active), Dave (age>22 AND active AND admin)
|
|
597
|
+
// Should NOT match: Bob (excluded by name filter), Charlie (age<=22, inactive, not admin)
|
|
598
|
+
expect(results.length).toBe(2);
|
|
599
|
+
const names = results.map(r => r.name).sort();
|
|
600
|
+
expect(names).toEqual(['Alice', 'Dave']);
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
|
|
542
604
|
test('should handle nin (not in) filter', async () => {
|
|
543
605
|
await driver.create('users', { name: 'Alice', status: 'active' });
|
|
544
606
|
await driver.create('users', { name: 'Bob', status: 'inactive' });
|