Skip to content

Commit ad62422

Browse files
committed
feat: allow creating of unique indexes
1 parent f8b5a99 commit ad62422

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

spec/schemas.spec.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3051,6 +3051,42 @@ describe('schemas', () => {
30513051
});
30523052
});
30533053

3054+
it('allows add unique index when you create a class', async () => {
3055+
await reconfigureServer({ silent: false });
3056+
const response = await request({
3057+
url: 'http://localhost:8378/1/schemas',
3058+
method: 'POST',
3059+
headers: masterKeyHeaders,
3060+
json: true,
3061+
body: {
3062+
className: 'NewClass',
3063+
fields: {
3064+
aString: { type: 'String' },
3065+
},
3066+
indexes: {
3067+
name1: { aString: 1, _options: { unique: true } },
3068+
},
3069+
},
3070+
});
3071+
expect(response.data).toEqual({
3072+
className: 'NewClass',
3073+
fields: {
3074+
ACL: { type: 'ACL' },
3075+
createdAt: { type: 'Date' },
3076+
updatedAt: { type: 'Date' },
3077+
objectId: { type: 'String' },
3078+
aString: { type: 'String' },
3079+
},
3080+
classLevelPermissions: defaultClassLevelPermissions,
3081+
indexes: {
3082+
name1: { aString: 1, _options: { unique: true } },
3083+
},
3084+
});
3085+
const indexes = await config.database.adapter.getIndexes('NewClass');
3086+
expect(indexes.length).toBe(2);
3087+
expect(indexes.filter(row => row.unique).length).toEqual(1);
3088+
});
3089+
30543090
it('empty index returns nothing', done => {
30553091
request({
30563092
url: 'http://localhost:8378/1/schemas',
@@ -3148,6 +3184,70 @@ describe('schemas', () => {
31483184
});
31493185
});
31503186

3187+
it('lets you add unique indexes', async () => {
3188+
await request({
3189+
url: 'http://localhost:8378/1/schemas/NewClass',
3190+
method: 'POST',
3191+
headers: masterKeyHeaders,
3192+
json: true,
3193+
body: {},
3194+
});
3195+
let response = await request({
3196+
url: 'http://localhost:8378/1/schemas/NewClass',
3197+
method: 'PUT',
3198+
headers: masterKeyHeaders,
3199+
json: true,
3200+
body: {
3201+
fields: {
3202+
aString: { type: 'String' },
3203+
},
3204+
indexes: {
3205+
name1: { aString: 1, _options: { unique: true } },
3206+
},
3207+
},
3208+
});
3209+
expect(
3210+
dd(response.data, {
3211+
className: 'NewClass',
3212+
fields: {
3213+
ACL: { type: 'ACL' },
3214+
createdAt: { type: 'Date' },
3215+
updatedAt: { type: 'Date' },
3216+
objectId: { type: 'String' },
3217+
aString: { type: 'String' },
3218+
},
3219+
classLevelPermissions: defaultClassLevelPermissions,
3220+
indexes: {
3221+
_id_: { _id: 1 },
3222+
name1: { aString: 1, _options: { unique: true } },
3223+
},
3224+
})
3225+
).toEqual(undefined);
3226+
response = await request({
3227+
url: 'http://localhost:8378/1/schemas/NewClass',
3228+
headers: masterKeyHeaders,
3229+
json: true,
3230+
});
3231+
expect(response.data).toEqual({
3232+
className: 'NewClass',
3233+
fields: {
3234+
ACL: { type: 'ACL' },
3235+
createdAt: { type: 'Date' },
3236+
updatedAt: { type: 'Date' },
3237+
objectId: { type: 'String' },
3238+
aString: { type: 'String' },
3239+
},
3240+
classLevelPermissions: defaultClassLevelPermissions,
3241+
indexes: {
3242+
_id_: { _id: 1 },
3243+
name1: { aString: 1, _options: { unique: true } },
3244+
},
3245+
});
3246+
const indexes = await config.database.adapter.getIndexes('NewClass');
3247+
expect(indexes.length).toEqual(2);
3248+
expect(indexes.filter(row => row.unique).length).toEqual(1);
3249+
});
3250+
31513251
it_only_db('mongo')('lets you add index with with pointer like structure', done => {
31523252
request({
31533253
url: 'http://localhost:8378/1/schemas/NewClass',

src/Adapters/Storage/Mongo/MongoStorageAdapter.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import MongoCollection from './MongoCollection';
33
import MongoSchemaCollection from './MongoSchemaCollection';
44
import { StorageAdapter } from '../StorageAdapter';
5+
import deepcopy from 'deepcopy';
56
import type { SchemaType, QueryType, StorageClass, QueryOptions } from '../StorageAdapter';
67
import { parse as parseUrl, format as formatUrl } from '../../../vendor/mongodbUrl';
78
import {
@@ -275,7 +276,13 @@ export class MongoStorageAdapter implements StorageAdapter {
275276
const deletePromises = [];
276277
const insertedIndexes = [];
277278
Object.keys(submittedIndexes).forEach(name => {
278-
const field = submittedIndexes[name];
279+
const field = deepcopy(submittedIndexes[name]);
280+
let indexOptions = {};
281+
if (field._options) {
282+
indexOptions = field._options;
283+
delete field._options;
284+
}
285+
console.log(existingIndexes[name], field);
279286
if (existingIndexes[name] && field.__op !== 'Delete') {
280287
throw new Parse.Error(Parse.Error.INVALID_QUERY, `Index ${name} exists, cannot update.`);
281288
}
@@ -303,11 +310,16 @@ export class MongoStorageAdapter implements StorageAdapter {
303310
);
304311
}
305312
});
306-
existingIndexes[name] = field;
307313
insertedIndexes.push({
308314
key: field,
309315
name,
316+
...indexOptions,
310317
});
318+
const fieldCopy = deepcopy(field);
319+
if (indexOptions) {
320+
fieldCopy._options = indexOptions;
321+
}
322+
existingIndexes[name] = fieldCopy;
311323
}
312324
});
313325
let insertPromise = Promise.resolve();

0 commit comments

Comments
 (0)