Skip to content
Merged
68 changes: 68 additions & 0 deletions spec/ParseQuery.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5306,4 +5306,72 @@ describe('Parse.Query testing', () => {
expect(score).toEqual([1]);
}, { useMasterKey: true });
});

describe_only_db('mongo')('query nested keys', () => {
it('queries nested key using equalTo', 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('queries nested key using containedIn', 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('queries nested key using matchesQuery', 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