Skip to content

Commit 7fac070

Browse files
authored
Allow queries with String array for pointers containedIn (#4188)
* Adds basic failing test * Adds ability to use [objectId] for $in/$nin pointers * makes sure to use a set field * Makes sure field is defined
1 parent 2a16893 commit 7fac070

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

spec/ParseQuery.spec.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2834,6 +2834,53 @@ describe('Parse.Query testing', () => {
28342834
});
28352835
});
28362836

2837+
it('containedIn with pointers should work with string array', done => {
2838+
const obj = new Parse.Object('MyClass');
2839+
const child = new Parse.Object('Child');
2840+
child.save().then(() => {
2841+
obj.set('child', child);
2842+
return obj.save();
2843+
}).then(() => {
2844+
const objs = [];
2845+
for(let i = 0; i < 10; i++) {
2846+
objs.push(new Parse.Object('MyClass'));
2847+
}
2848+
return Parse.Object.saveAll(objs);
2849+
}).then(() => {
2850+
const query = new Parse.Query('MyClass');
2851+
query.containedIn('child', [child.id]);
2852+
return query.find();
2853+
}).then((results) => {
2854+
expect(results.length).toBe(1);
2855+
}).then(done).catch(done.fail);
2856+
});
2857+
2858+
it('containedIn with pointers should work with string array, with many objects', done => {
2859+
const objs = [];
2860+
const children = [];
2861+
for(let i = 0; i < 10; i++) {
2862+
const obj = new Parse.Object('MyClass');
2863+
const child = new Parse.Object('Child');
2864+
objs.push(obj);
2865+
children.push(child);
2866+
}
2867+
Parse.Object.saveAll(children).then(() => {
2868+
return Parse.Object.saveAll(objs.map((obj, i) => {
2869+
obj.set('child', children[i]);
2870+
return obj;
2871+
}));
2872+
}).then(() => {
2873+
const query = new Parse.Query('MyClass');
2874+
const subset = children.slice(0, 5).map((child) => {
2875+
return child.id;
2876+
});
2877+
query.containedIn('child', subset);
2878+
return query.find();
2879+
}).then((results) => {
2880+
expect(results.length).toBe(5);
2881+
}).then(done).catch(done.fail);
2882+
});
2883+
28372884
it('include for specific object', function(done){
28382885
var child = new Parse.Object('Child');
28392886
var parent = new Parse.Object('Parent');

src/Adapters/Storage/Mongo/MongoTransform.js

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -241,12 +241,13 @@ function transformQueryKeyValue(className, key, value, schema) {
241241
schema.fields[key] &&
242242
schema.fields[key].type === 'Pointer';
243243

244+
const field = schema && schema.fields[key];
244245
if (expectedTypeIsPointer || !schema && value && value.__type === 'Pointer') {
245246
key = '_p_' + key;
246247
}
247248

248249
// Handle query constraints
249-
const transformedConstraint = transformConstraint(value, expectedTypeIsArray);
250+
const transformedConstraint = transformConstraint(value, field);
250251
if (transformedConstraint !== CannotTransform) {
251252
if (transformedConstraint.$text) {
252253
return {key: '$text', value: transformedConstraint.$text};
@@ -454,7 +455,7 @@ const addLegacyACL = restObject => {
454455
// cannot perform a transformation
455456
function CannotTransform() {}
456457

457-
const transformInteriorAtom = atom => {
458+
const transformInteriorAtom = (atom) => {
458459
// TODO: check validity harder for the __type-defined types
459460
if (typeof atom === 'object' && atom && !(atom instanceof Date) && atom.__type === 'Pointer') {
460461
return {
@@ -480,14 +481,17 @@ const transformInteriorAtom = atom => {
480481
// or arrays with generic stuff inside.
481482
// Raises an error if this cannot possibly be valid REST format.
482483
// Returns CannotTransform if it's just not an atom
483-
function transformTopLevelAtom(atom) {
484+
function transformTopLevelAtom(atom, field) {
484485
switch(typeof atom) {
485-
case 'string':
486486
case 'number':
487487
case 'boolean':
488-
return atom;
489488
case 'undefined':
490489
return atom;
490+
case 'string':
491+
if (field && field.type === 'Pointer') {
492+
return `${field.targetClass}$${atom}`;
493+
}
494+
return atom;
491495
case 'symbol':
492496
case 'function':
493497
throw new Parse.Error(Parse.Error.INVALID_JSON, `cannot transform value: ${atom}`);
@@ -534,13 +538,14 @@ function transformTopLevelAtom(atom) {
534538
// If it is not a valid constraint but it could be a valid something
535539
// else, return CannotTransform.
536540
// inArray is whether this is an array field.
537-
function transformConstraint(constraint, inArray) {
541+
function transformConstraint(constraint, field) {
542+
const inArray = field && field.type && field.type === 'Array';
538543
if (typeof constraint !== 'object' || !constraint) {
539544
return CannotTransform;
540545
}
541546
const transformFunction = inArray ? transformInteriorAtom : transformTopLevelAtom;
542547
const transformer = (atom) => {
543-
const result = transformFunction(atom);
548+
const result = transformFunction(atom, field);
544549
if (result === CannotTransform) {
545550
throw new Parse.Error(Parse.Error.INVALID_JSON, `bad atom: ${JSON.stringify(atom)}`);
546551
}

0 commit comments

Comments
 (0)