Skip to content

Commit 145f948

Browse files
committed
feat: add MongoDB 5.2 support (#7894)
1 parent 44f0bae commit 145f948

File tree

4 files changed

+107
-18
lines changed

4 files changed

+107
-18
lines changed

Diff for: .github/workflows/ci.yml

+7-2
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,18 @@ jobs:
101101
strategy:
102102
matrix:
103103
include:
104+
- name: MongoDB 5.2, ReplicaSet, WiredTiger
105+
MONGODB_VERSION: 5.2.1
106+
MONGODB_TOPOLOGY: replicaset
107+
MONGODB_STORAGE_ENGINE: wiredTiger
108+
NODE_VERSION: 14.18.1
104109
- name: MongoDB 5.1, ReplicaSet, WiredTiger
105-
MONGODB_VERSION: 5.1.0
110+
MONGODB_VERSION: 5.1.1
106111
MONGODB_TOPOLOGY: replicaset
107112
MONGODB_STORAGE_ENGINE: wiredTiger
108113
NODE_VERSION: 14.18.1
109114
- name: MongoDB 5.0, ReplicaSet, WiredTiger
110-
MONGODB_VERSION: 5.0.3
115+
MONGODB_VERSION: 5.0.6
111116
MONGODB_TOPOLOGY: replicaset
112117
MONGODB_STORAGE_ENGINE: wiredTiger
113118
NODE_VERSION: 16.13.0

Diff for: README.md

+8-7
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,14 @@ Parse Server is continuously tested with the most recent releases of Node.js to
122122
#### MongoDB
123123
Parse Server is continuously tested with the most recent releases of MongoDB to ensure compatibility. We follow the [MongoDB support schedule](https://www.mongodb.com/support-policy) and only test against versions that are officially supported and have not reached their end-of-life date.
124124

125-
| Version | Latest Version | End-of-Life | Compatible |
126-
|-------------|----------------|--------------|------------|
127-
| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes |
128-
| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes |
129-
| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes |
130-
| MongoDB 5.0 | 5.0.3 | January 2024 | ✅ Yes |
131-
| MongoDB 5.1 | 5.1.0 | January 2024 | ✅ Yes |
125+
| Version | Latest Version | End-of-Life | Compatible |
126+
|-------------|----------------|-------------|------------|
127+
| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes |
128+
| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes |
129+
| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes |
130+
| MongoDB 5.0 | 5.0.6 | TBD | ✅ Yes |
131+
| MongoDB 5.1 | 5.1.1 | TBD | ✅ Yes |
132+
| MongoDB 5.2 | 5.2.1 | TBD | ✅ Yes |
132133

133134
#### PostgreSQL
134135
Parse Server is continuously tested with the most recent releases of PostgreSQL and PostGIS to ensure compatibility, using [PostGIS docker images](https://registry.hub.docker.com/r/postgis/postgis/tags?page=1&ordering=last_updated). We follow the [PostgreSQL support schedule](https://www.postgresql.org/support/versioning) and [PostGIS support schedule](https://www.postgis.net/eol_policy/) and only test against versions that are officially supported and have not reached their end-of-life date. Due to the extensive PostgreSQL support duration of 5 years, Parse Server drops support if a version is older than 3.5 years and a newer version has been available for at least 2.5 years.

Diff for: package.json

+7-6
Original file line numberDiff line numberDiff line change
@@ -119,14 +119,15 @@
119119
"test:mongodb:4.0.27": "npm run test:mongodb --dbversion=4.0.27",
120120
"test:mongodb:4.2.17": "npm run test:mongodb --dbversion=4.2.17",
121121
"test:mongodb:4.4.10": "npm run test:mongodb --dbversion=4.4.10",
122-
"test:mongodb:5.0.5": "npm run test:mongodb --dbversion=5.0.5",
123-
"test:mongodb:5.1.0": "npm run test:mongodb --dbversion=5.1.0",
122+
"test:mongodb:5.0.6": "npm run test:mongodb --dbversion=5.0.6",
123+
"test:mongodb:5.1.1": "npm run test:mongodb --dbversion=5.1.1",
124+
"test:mongodb:5.2.1": "npm run test:mongodb --dbversion=5.2.1",
124125
"posttest:mongodb": "mongodb-runner stop",
125-
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start",
126-
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine",
126+
"pretest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner start",
127+
"testonly": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 jasmine",
127128
"test": "npm run testonly",
128-
"posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop",
129-
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.1.0} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine",
129+
"posttest": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} mongodb-runner stop",
130+
"coverage": "cross-env MONGODB_VERSION=${MONGODB_VERSION:=5.2.1} MONGODB_TOPOLOGY=${MONGODB_TOPOLOGY:=standalone} MONGODB_STORAGE_ENGINE=${MONGODB_STORAGE_ENGINE:=wiredTiger} TESTING=1 nyc jasmine",
130131
"start": "node ./bin/parse-server",
131132
"prettier": "prettier --write {src,spec}/{**/*,*}.js",
132133
"prepare": "npm run build",

Diff for: spec/ParseQuery.hint.spec.js

+85-3
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
122122
expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_');
123123
});
124124

125-
it_only_mongodb_version('>=5.1')('query aggregate with hint string', async () => {
125+
it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint string', async () => {
126126
const object = new TestObject({ foo: 'bar' });
127127
await object.save();
128128

@@ -146,6 +146,30 @@ describe_only_db('mongo')('Parse.Query hint', () => {
146146
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
147147
});
148148

149+
it_only_mongodb_version('>=5.2')('query aggregate with hint string', async () => {
150+
const object = new TestObject({ foo: 'bar' });
151+
await object.save();
152+
153+
const collection = await config.database.adapter._adaptiveCollection('TestObject');
154+
let result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
155+
explain: true,
156+
});
157+
let queryPlanner = result[0].queryPlanner;
158+
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
159+
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN');
160+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined();
161+
162+
result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
163+
hint: '_id_',
164+
explain: true,
165+
});
166+
queryPlanner = result[0].queryPlanner;
167+
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
168+
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH');
169+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN');
170+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
171+
});
172+
149173
it_only_mongodb_version('<4.4')('query aggregate with hint object', async () => {
150174
const object = new TestObject({ foo: 'bar' });
151175
await object.save();
@@ -191,7 +215,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
191215
expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
192216
});
193217

194-
it_only_mongodb_version('>=5.1')('query aggregate with hint object', async () => {
218+
it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint object', async () => {
195219
const object = new TestObject({ foo: 'bar' });
196220
await object.save();
197221

@@ -216,6 +240,31 @@ describe_only_db('mongo')('Parse.Query hint', () => {
216240
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
217241
});
218242

243+
it_only_mongodb_version('>=5.2')('query aggregate with hint object', async () => {
244+
const object = new TestObject({ foo: 'bar' });
245+
await object.save();
246+
247+
const collection = await config.database.adapter._adaptiveCollection('TestObject');
248+
let result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
249+
explain: true,
250+
});
251+
let queryPlanner = result[0].queryPlanner;
252+
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
253+
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN');
254+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined();
255+
256+
result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
257+
hint: { _id: 1 },
258+
explain: true,
259+
});
260+
queryPlanner = result[0].queryPlanner;
261+
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
262+
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH');
263+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN');
264+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
265+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
266+
});
267+
219268
it_only_mongodb_version('<5.1')('query find with hint (rest)', async () => {
220269
const object = new TestObject();
221270
await object.save();
@@ -326,7 +375,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
326375
expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
327376
});
328377

329-
it_only_mongodb_version('>=5.1')('query aggregate with hint (rest)', async () => {
378+
it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint (rest)', async () => {
330379
const object = new TestObject({ foo: 'bar' });
331380
await object.save();
332381
let options = Object.assign({}, masterKeyOptions, {
@@ -358,4 +407,37 @@ describe_only_db('mongo')('Parse.Query hint', () => {
358407
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
359408
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
360409
});
410+
411+
it_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => {
412+
const object = new TestObject({ foo: 'bar' });
413+
await object.save();
414+
let options = Object.assign({}, masterKeyOptions, {
415+
url: Parse.serverURL + '/aggregate/TestObject',
416+
qs: {
417+
explain: true,
418+
group: JSON.stringify({ objectId: '$foo' }),
419+
},
420+
});
421+
let response = await request(options);
422+
let queryPlanner = response.data.results[0].queryPlanner;
423+
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
424+
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN');
425+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined();
426+
427+
options = Object.assign({}, masterKeyOptions, {
428+
url: Parse.serverURL + '/aggregate/TestObject',
429+
qs: {
430+
explain: true,
431+
hint: '_id_',
432+
group: JSON.stringify({ objectId: '$foo' }),
433+
},
434+
});
435+
response = await request(options);
436+
queryPlanner = response.data.results[0].queryPlanner;
437+
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
438+
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH');
439+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN');
440+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
441+
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
442+
});
361443
});

0 commit comments

Comments
 (0)