diff --git a/spec/ParseRelation.spec.js b/spec/ParseRelation.spec.js index e8e7258c..664a9ba9 100644 --- a/spec/ParseRelation.spec.js +++ b/spec/ParseRelation.spec.js @@ -237,7 +237,57 @@ describe('Parse.Relation testing', () => { success: function(list) { equal(list.length, 1, "There should be only one result"); equal(list[0].id, parent2.id, - "Should have gotten back the right result"); + "Should have gotten back the right result"); + done(); + } + }); + } + }); + } + }); + }); + + it("queries on relation fields with multiple ins", (done) => { + var ChildObject = Parse.Object.extend("ChildObject"); + var childObjects = []; + for (var i = 0; i < 10; i++) { + childObjects.push(new ChildObject({x: i})); + } + + Parse.Object.saveAll(childObjects, { + success: function() { + var ParentObject = Parse.Object.extend("ParentObject"); + var parent = new ParentObject(); + parent.set("x", 4); + var relation = parent.relation("child"); + relation.add(childObjects[0]); + relation.add(childObjects[1]); + relation.add(childObjects[2]); + var parent2 = new ParentObject(); + parent2.set("x", 3); + var relation2 = parent2.relation("child"); + relation2.add(childObjects[4]); + relation2.add(childObjects[5]); + relation2.add(childObjects[6]); + + var otherChild2 = parent2.relation("otherChild"); + otherChild2.add(childObjects[0]); + otherChild2.add(childObjects[1]); + otherChild2.add(childObjects[2]); + + var parents = []; + parents.push(parent); + parents.push(parent2); + Parse.Object.saveAll(parents, { + success: function() { + var query = new Parse.Query(ParentObject); + var objects = []; + objects.push(childObjects[0]); + query.containedIn("child", objects); + query.containedIn("otherChild", [childObjects[0]]); + query.find({ + success: function(list) { + equal(list.length, 2, "There should be only one result"); done(); } }); diff --git a/src/Controllers/DatabaseController.js b/src/Controllers/DatabaseController.js index a7d26245..8901004d 100644 --- a/src/Controllers/DatabaseController.js +++ b/src/Controllers/DatabaseController.js @@ -397,31 +397,33 @@ DatabaseController.prototype.owningIds = function(className, key, relatedIds) { // Modifies query so that it no longer has $in on relation fields, or // equal-to-pointer constraints on relation fields. // Returns a promise that resolves when query is mutated -// TODO: this only handles one of these at a time - make it handle more DatabaseController.prototype.reduceInRelation = function(className, query, schema) { // Search for an in-relation or equal-to-relation - for (var key in query) { - if (query[key] && - (query[key]['$in'] || query[key].__type == 'Pointer')) { - var t = schema.getExpectedType(className, key); - var match = t ? t.match(/^relation<(.*)>$/) : false; - if (!match) { - continue; + // Make it sequential for now, not sure of paralleization side effects + return Object.keys(query).reduce((promise, key) => { + return promise.then(() => { + if (query[key] && + (query[key]['$in'] || query[key].__type == 'Pointer')) { + let t = schema.getExpectedType(className, key); + let match = t ? t.match(/^relation<(.*)>$/) : false; + if (!match) { + return; + } + let relatedClassName = match[1]; + let relatedIds; + if (query[key]['$in']) { + relatedIds = query[key]['$in'].map(r => r.objectId); + } else { + relatedIds = [query[key].objectId]; + } + return this.owningIds(className, key, relatedIds).then((ids) => { + delete query[key]; + query.objectId = Object.assign({'$in': []}, query.objectId); + query.objectId['$in'] = query.objectId['$in'].concat(ids); + }); } - var relatedClassName = match[1]; - var relatedIds; - if (query[key]['$in']) { - relatedIds = query[key]['$in'].map(r => r.objectId); - } else { - relatedIds = [query[key].objectId]; - } - return this.owningIds(className, key, relatedIds).then((ids) => { - delete query[key]; - query.objectId = {'$in': ids}; - }); - } - } - return Promise.resolve(); + }); + }, Promise.resolve()); }; // Modifies query so that it no longer has $relatedTo