feat: add MongoDB 5.2 support (#7894)

This commit is contained in:
Manuel
2022-03-27 22:44:02 +02:00
committed by Manuel Trezza
parent 38eb5ace37
commit 5bfa7160d9
4 changed files with 107 additions and 18 deletions

View File

@@ -101,13 +101,18 @@ jobs:
strategy: strategy:
matrix: matrix:
include: include:
- name: MongoDB 5.2, ReplicaSet, WiredTiger
MONGODB_VERSION: 5.2.1
MONGODB_TOPOLOGY: replicaset
MONGODB_STORAGE_ENGINE: wiredTiger
NODE_VERSION: 14.18.1
- name: MongoDB 5.1, ReplicaSet, WiredTiger - name: MongoDB 5.1, ReplicaSet, WiredTiger
MONGODB_VERSION: 5.1.0 MONGODB_VERSION: 5.1.1
MONGODB_TOPOLOGY: replicaset MONGODB_TOPOLOGY: replicaset
MONGODB_STORAGE_ENGINE: wiredTiger MONGODB_STORAGE_ENGINE: wiredTiger
NODE_VERSION: 14.18.1 NODE_VERSION: 14.18.1
- name: MongoDB 5.0, ReplicaSet, WiredTiger - name: MongoDB 5.0, ReplicaSet, WiredTiger
MONGODB_VERSION: 5.0.3 MONGODB_VERSION: 5.0.6
MONGODB_TOPOLOGY: replicaset MONGODB_TOPOLOGY: replicaset
MONGODB_STORAGE_ENGINE: wiredTiger MONGODB_STORAGE_ENGINE: wiredTiger
NODE_VERSION: 16.13.0 NODE_VERSION: 16.13.0

View File

@@ -123,12 +123,13 @@ Parse Server is continuously tested with the most recent releases of Node.js to
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. 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.
| Version | Latest Version | End-of-Life | Compatible | | Version | Latest Version | End-of-Life | Compatible |
|-------------|----------------|--------------|------------| |-------------|----------------|-------------|------------|
| MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes | | MongoDB 4.0 | 4.0.27 | April 2022 | ✅ Yes |
| MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes | | MongoDB 4.2 | 4.2.17 | TBD | ✅ Yes |
| MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes | | MongoDB 4.4 | 4.4.10 | TBD | ✅ Yes |
| MongoDB 5.0 | 5.0.3 | January 2024 | ✅ Yes | | MongoDB 5.0 | 5.0.6 | TBD | ✅ Yes |
| MongoDB 5.1 | 5.1.0 | January 2024 | ✅ Yes | | MongoDB 5.1 | 5.1.1 | TBD | ✅ Yes |
| MongoDB 5.2 | 5.2.1 | TBD | ✅ Yes |
#### PostgreSQL #### PostgreSQL
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. 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.

View File

@@ -119,14 +119,15 @@
"test:mongodb:4.0.27": "npm run test:mongodb --dbversion=4.0.27", "test:mongodb:4.0.27": "npm run test:mongodb --dbversion=4.0.27",
"test:mongodb:4.2.17": "npm run test:mongodb --dbversion=4.2.17", "test:mongodb:4.2.17": "npm run test:mongodb --dbversion=4.2.17",
"test:mongodb:4.4.10": "npm run test:mongodb --dbversion=4.4.10", "test:mongodb:4.4.10": "npm run test:mongodb --dbversion=4.4.10",
"test:mongodb:5.0.5": "npm run test:mongodb --dbversion=5.0.5", "test:mongodb:5.0.6": "npm run test:mongodb --dbversion=5.0.6",
"test:mongodb:5.1.0": "npm run test:mongodb --dbversion=5.1.0", "test:mongodb:5.1.1": "npm run test:mongodb --dbversion=5.1.1",
"test:mongodb:5.2.1": "npm run test:mongodb --dbversion=5.2.1",
"posttest:mongodb": "mongodb-runner stop", "posttest:mongodb": "mongodb-runner stop",
"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", "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",
"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", "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",
"test": "npm run testonly", "test": "npm run testonly",
"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", "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",
"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", "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",
"start": "node ./bin/parse-server", "start": "node ./bin/parse-server",
"prettier": "prettier --write {src,spec}/{**/*,*}.js", "prettier": "prettier --write {src,spec}/{**/*,*}.js",
"prepare": "npm run build", "prepare": "npm run build",

View File

@@ -122,7 +122,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_');
}); });
it_only_mongodb_version('>=5.1')('query aggregate with hint string', async () => { it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint string', async () => {
const object = new TestObject({ foo: 'bar' }); const object = new TestObject({ foo: 'bar' });
await object.save(); await object.save();
@@ -146,6 +146,30 @@ describe_only_db('mongo')('Parse.Query hint', () => {
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
}); });
it_only_mongodb_version('>=5.2')('query aggregate with hint string', async () => {
const object = new TestObject({ foo: 'bar' });
await object.save();
const collection = await config.database.adapter._adaptiveCollection('TestObject');
let result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
explain: true,
});
let queryPlanner = result[0].queryPlanner;
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined();
result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
hint: '_id_',
explain: true,
});
queryPlanner = result[0].queryPlanner;
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
});
it_only_mongodb_version('<4.4')('query aggregate with hint object', async () => { it_only_mongodb_version('<4.4')('query aggregate with hint object', async () => {
const object = new TestObject({ foo: 'bar' }); const object = new TestObject({ foo: 'bar' });
await object.save(); await object.save();
@@ -191,7 +215,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
}); });
it_only_mongodb_version('>=5.1')('query aggregate with hint object', async () => { it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint object', async () => {
const object = new TestObject({ foo: 'bar' }); const object = new TestObject({ foo: 'bar' });
await object.save(); await object.save();
@@ -216,6 +240,31 @@ describe_only_db('mongo')('Parse.Query hint', () => {
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
}); });
it_only_mongodb_version('>=5.2')('query aggregate with hint object', async () => {
const object = new TestObject({ foo: 'bar' });
await object.save();
const collection = await config.database.adapter._adaptiveCollection('TestObject');
let result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
explain: true,
});
let queryPlanner = result[0].queryPlanner;
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined();
result = await collection.aggregate([{ $group: { _id: '$foo' } }], {
hint: { _id: 1 },
explain: true,
});
queryPlanner = result[0].queryPlanner;
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
});
it_only_mongodb_version('<5.1')('query find with hint (rest)', async () => { it_only_mongodb_version('<5.1')('query find with hint (rest)', async () => {
const object = new TestObject(); const object = new TestObject();
await object.save(); await object.save();
@@ -326,7 +375,7 @@ describe_only_db('mongo')('Parse.Query hint', () => {
expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); expect(queryPlanner.winningPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
}); });
it_only_mongodb_version('>=5.1')('query aggregate with hint (rest)', async () => { it_only_mongodb_version('>=5.1<5.2')('query aggregate with hint (rest)', async () => {
const object = new TestObject({ foo: 'bar' }); const object = new TestObject({ foo: 'bar' });
await object.save(); await object.save();
let options = Object.assign({}, masterKeyOptions, { let options = Object.assign({}, masterKeyOptions, {
@@ -358,4 +407,37 @@ describe_only_db('mongo')('Parse.Query hint', () => {
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
}); });
it_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => {
const object = new TestObject({ foo: 'bar' });
await object.save();
let options = Object.assign({}, masterKeyOptions, {
url: Parse.serverURL + '/aggregate/TestObject',
qs: {
explain: true,
group: JSON.stringify({ objectId: '$foo' }),
},
});
let response = await request(options);
let queryPlanner = response.data.results[0].queryPlanner;
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('COLLSCAN');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage).toBeUndefined();
options = Object.assign({}, masterKeyOptions, {
url: Parse.serverURL + '/aggregate/TestObject',
qs: {
explain: true,
hint: '_id_',
group: JSON.stringify({ objectId: '$foo' }),
},
});
response = await request(options);
queryPlanner = response.data.results[0].queryPlanner;
expect(queryPlanner.winningPlan.queryPlan.stage).toBe('GROUP');
expect(queryPlanner.winningPlan.queryPlan.inputStage.stage).toBe('FETCH');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_');
expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 });
});
}); });