Skip to content

Commit f0a6248

Browse files
committed
Fixed $elemMatch operator handling
1 parent d7d94a0 commit f0a6248

File tree

3 files changed

+50
-29
lines changed

3 files changed

+50
-29
lines changed

src/packages/pongo/src/e2e/compatibilityTest.e2e.spec.ts

+22-22
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ void describe('MongoDB Compatibility Tests', () => {
7777
const pongoCollection = pongoDb.collection<User>('testCollection');
7878
const mongoCollection = mongoDb.collection<User>('testCollection');
7979

80-
const doc = { name: 'Alice', age: 25 };
80+
const doc = { name: 'Anita', age: 25 };
8181

8282
const pongoInsertResult = await pongoCollection.insertOne(doc);
8383
const mongoInsertResult = await mongoCollection.insertOne(doc);
@@ -109,7 +109,7 @@ void describe('MongoDB Compatibility Tests', () => {
109109
void it('should update a document in both PostgreSQL and MongoDB', async () => {
110110
const pongoCollection = pongoDb.collection<User>('testCollection');
111111
const mongoCollection = mongoDb.collection<User>('testCollection');
112-
const doc = { name: 'Bob', age: 30 };
112+
const doc = { name: 'Roger', age: 30 };
113113

114114
const pongoInsertResult = await pongoCollection.insertOne(doc);
115115
const mongoInsertResult = await mongoCollection.insertOne(doc);
@@ -149,7 +149,7 @@ void describe('MongoDB Compatibility Tests', () => {
149149
void it('should delete a document from both PostgreSQL and MongoDB', async () => {
150150
const pongoCollection = pongoDb.collection<User>('testCollection');
151151
const mongoCollection = mongoDb.collection<User>('testCollection');
152-
const doc = { name: 'Charlie', age: 35 };
152+
const doc = { name: 'Cruella', age: 35 };
153153

154154
const pongoInsertResult = await pongoCollection.insertOne(doc);
155155
const mongoInsertResult = await mongoCollection.insertOne(doc);
@@ -278,17 +278,17 @@ void describe('MongoDB Compatibility Tests', () => {
278278

279279
const docs = [
280280
{
281-
name: 'Alice',
281+
name: 'Anita',
282282
age: 25,
283283
address: { city: 'Wonderland', street: 'Main St' },
284284
},
285285
{
286-
name: 'Bob',
286+
name: 'Roger',
287287
age: 30,
288288
address: { city: 'Wonderland', street: 'Elm St' },
289289
},
290290
{
291-
name: 'Charlie',
291+
name: 'Cruella',
292292
age: 35,
293293
address: { city: 'Dreamland', street: 'Oak St' },
294294
},
@@ -329,17 +329,17 @@ void describe('MongoDB Compatibility Tests', () => {
329329

330330
const docs = [
331331
{
332-
name: 'Alice',
332+
name: 'Anita',
333333
age: 25,
334334
address: { city: 'Wonderland', street: 'Main St' },
335335
},
336336
{
337-
name: 'Bob',
337+
name: 'Roger',
338338
age: 30,
339339
address: { city: 'Wonderland', street: 'Elm St' },
340340
},
341341
{
342-
name: 'Charlie',
342+
name: 'Cruella',
343343
age: 35,
344344
address: { city: 'Dreamland', street: 'Oak St' },
345345
},
@@ -380,9 +380,9 @@ void describe('MongoDB Compatibility Tests', () => {
380380
const mongoCollection = mongoDb.collection<User>('testCollection');
381381

382382
const docs = [
383-
{ name: 'Alice', age: 25, tags: ['tag1', 'tag2'] },
384-
{ name: 'Bob', age: 30, tags: ['tag2', 'tag3'] },
385-
{ name: 'Charlie', age: 35, tags: ['tag1', 'tag3'] },
383+
{ name: 'Anita', age: 25, tags: ['tag1', 'tag2'] },
384+
{ name: 'Roger', age: 30, tags: ['tag2', 'tag3'] },
385+
{ name: 'Cruella', age: 35, tags: ['tag1', 'tag3'] },
386386
];
387387

388388
await pongoCollection.insertOne(docs[0]!);
@@ -407,9 +407,9 @@ void describe('MongoDB Compatibility Tests', () => {
407407
const mongoCollection = mongoDb.collection<User>('testCollection');
408408

409409
const docs = [
410-
{ name: 'Alice', age: 25, tags: ['tag1', 'tag2'] },
411-
{ name: 'Bob', age: 30, tags: ['tag2', 'tag3'] },
412-
{ name: 'Charlie', age: 35, tags: ['tag1', 'tag3'] },
410+
{ name: 'Anita', age: 25, tags: ['tag1', 'tag2'] },
411+
{ name: 'Roger', age: 30, tags: ['tag2', 'tag3'] },
412+
{ name: 'Cruella', age: 35, tags: ['tag1', 'tag3'] },
413413
];
414414

415415
await pongoCollection.insertOne(docs[0]!);
@@ -438,9 +438,9 @@ void describe('MongoDB Compatibility Tests', () => {
438438
const mongoCollection = mongoDb.collection<User>('testCollection');
439439

440440
const docs = [
441-
{ name: 'Alice', age: 25, tags: ['tag1', 'tag2'] },
442-
{ name: 'Bob', age: 30, tags: ['tag2', 'tag3'] },
443-
{ name: 'Charlie', age: 35, tags: ['tag1', 'tag3'] },
441+
{ name: 'Anita', age: 25, tags: ['tag1', 'tag2'] },
442+
{ name: 'Roger', age: 30, tags: ['tag2', 'tag3'] },
443+
{ name: 'Cruella', age: 35, tags: ['tag1', 'tag3'] },
444444
];
445445

446446
await pongoCollection.insertOne(docs[0]!);
@@ -464,13 +464,13 @@ void describe('MongoDB Compatibility Tests', () => {
464464
);
465465
});
466466

467-
void it.skip('should find documents with a nested array element match filter in both PostgreSQL and MongoDB', async () => {
467+
void it('should find documents with a nested array element match filter in both PostgreSQL and MongoDB', async () => {
468468
const pongoCollection = pongoDb.collection<User>('testCollection');
469469
const mongoCollection = mongoDb.collection<User>('testCollection');
470470

471471
const docs = [
472472
{
473-
name: 'Alice',
473+
name: 'Anita',
474474
age: 25,
475475
address: {
476476
city: 'Wonderland',
@@ -479,7 +479,7 @@ void describe('MongoDB Compatibility Tests', () => {
479479
},
480480
},
481481
{
482-
name: 'Bob',
482+
name: 'Roger',
483483
age: 30,
484484
address: {
485485
city: 'Wonderland',
@@ -488,7 +488,7 @@ void describe('MongoDB Compatibility Tests', () => {
488488
},
489489
},
490490
{
491-
name: 'Charlie',
491+
name: 'Cruella',
492492
age: 35,
493493
address: {
494494
city: 'Dreamland',

src/packages/pongo/src/postgres/filter/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { PongoFilter } from '../../main';
2-
import { handleOperator, hasOperators } from './queryOperators';
2+
import { Operators, handleOperator, hasOperators } from './queryOperators';
33

44
const AND = 'AND';
55

@@ -22,7 +22,7 @@ const constructComplexFilterQuery = (
2222
.map(
2323
([nestedKey, val]) =>
2424
isEquality
25-
? handleOperator(`${key}.${nestedKey}`, '$eq', val) //regular value
25+
? handleOperator(`${key}.${nestedKey}`, Operators.$eq, val) // regular value
2626
: handleOperator(key, nestedKey, val), // operator
2727
)
2828
.join(` ${AND} `);

src/packages/pongo/src/postgres/filter/queryOperators.ts

+26-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
import format from 'pg-format';
22

3-
const operatorMap = {
3+
export const Operators = {
4+
$eq: '$eq',
5+
$gt: '$gt',
6+
$gte: '$gte',
7+
$lt: '$lt',
8+
$lte: '$lte',
9+
$ne: '$ne',
10+
$in: '$in',
11+
$nin: '$nin',
12+
$elemMatch: '$elemMatch',
13+
$all: '$all',
14+
$size: '$size',
15+
};
16+
17+
const OperatorMap = {
418
$gt: '>',
519
$gte: '>=',
620
$lt: '<',
@@ -32,7 +46,7 @@ export const handleOperator = (
3246
case '$lte':
3347
case '$ne':
3448
return format(
35-
`data #>> %L ${operatorMap[operator]} %L`,
49+
`data #>> %L ${OperatorMap[operator]} %L`,
3650
`{${path.split('.').join(',')}}`,
3751
value,
3852
);
@@ -48,11 +62,18 @@ export const handleOperator = (
4862
`{${path.split('.').join(',')}}`,
4963
(value as unknown[]).map((v) => format('%L', v)).join(', '),
5064
);
51-
case '$elemMatch':
65+
case '$elemMatch': {
66+
const subQuery = Object.entries(value as Record<string, unknown>)
67+
.map(([subKey, subValue]) =>
68+
format(`@."%s" == %s`, subKey, JSON.stringify(subValue)),
69+
)
70+
.join(' && ');
5271
return format(
53-
'data @> %L::jsonb',
54-
JSON.stringify(buildNestedObject(path, { $elemMatch: value })),
72+
`jsonb_path_exists(data, '$.%s[*] ? (%s)')`,
73+
path,
74+
subQuery,
5575
);
76+
}
5677
case '$all':
5778
return format(
5879
'data @> %L::jsonb',

0 commit comments

Comments
 (0)