Skip to content

fix: Parse.Query.containedIn and matchesQuery do not work with nested objects #9738

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: alpha
Choose a base branch
from
72 changes: 72 additions & 0 deletions spec/ParseQuery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5306,4 +5306,76 @@ describe('Parse.Query testing', () => {
expect(score).toEqual([1]);
}, { useMasterKey: true });
});

describe_only_db('mongo')('check if containedIn and matchesQuery works with nested keys', () => {
/**
* If we use equalTo to compare the nested pointer it works
* But it does not work with contained in or matchesQuery
*/
it('Parse query works with nested objects if equal to is used', async () => {
const child = new Parse.Object('Child');
child.set('key', 'value');
await child.save();

const parent = new Parse.Object('Parent');
parent.set('some', {
nested: {
key: {
child,
},
},
});
await parent.save();

const query1 = await new Parse.Query('Parent')
.equalTo('some.nested.key.child', child)
.find();

expect(query1.length).toEqual(1);
});

it('Parse query works when containedIn is used', async () => {
const child = new Parse.Object('Child');
child.set('key', 'value');
await child.save();

const parent = new Parse.Object('Parent');
parent.set('some', {
nested: {
key: {
child,
},
},
});
await parent.save();

const query1 = await new Parse.Query('Parent')
.containedIn('some.nested.key.child', [child])
.find();

expect(query1.length).toEqual(1);
});

it('Parse query works when matchesQuery is used which in turn uses contained in', async () => {
const child = new Parse.Object('Child');
child.set('key', 'value');
await child.save();

const parent = new Parse.Object('Parent');
parent.set('some', {
nested: {
key: {
child,
},
},
});
await parent.save();

const query1 = await new Parse.Query('Parent')
.matchesQuery('some.nested.key.child', new Parse.Query('Child').equalTo('key', 'value'))
.find();

expect(query1.length).toEqual(1);
});
});
});
9 changes: 6 additions & 3 deletions src/Adapters/Storage/Mongo/MongoTransform.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ function transformQueryKeyValue(className, key, value, schema, count = false) {
}

// Handle query constraints
const transformedConstraint = transformConstraint(value, field, count);
const transformedConstraint = transformConstraint(value, field, key, count);
if (transformedConstraint !== CannotTransform) {
if (transformedConstraint.$text) {
return { key: '$text', value: transformedConstraint.$text };
Expand Down Expand Up @@ -651,12 +651,15 @@ function transformTopLevelAtom(atom, field) {
// If it is not a valid constraint but it could be a valid something
// else, return CannotTransform.
// inArray is whether this is an array field.
function transformConstraint(constraint, field, count = false) {
function transformConstraint(constraint, field, queryKey, count = false) {
const inArray = field && field.type && field.type === 'Array';
// Check wether the given key has `.`
const isNestedKey = queryKey.indexOf('.') > -1;
if (typeof constraint !== 'object' || !constraint) {
return CannotTransform;
}
const transformFunction = inArray ? transformInteriorAtom : transformTopLevelAtom;
// For inArray or nested key, we need to transform the interior atom
const transformFunction = (inArray || isNestedKey) ? transformInteriorAtom : transformTopLevelAtom;
const transformer = atom => {
const result = transformFunction(atom, field);
if (result === CannotTransform) {
Expand Down
Loading