diff --git a/integration/test/ParseQueryTest.js b/integration/test/ParseQueryTest.js index 763021000..16ec9d92e 100644 --- a/integration/test/ParseQueryTest.js +++ b/integration/test/ParseQueryTest.js @@ -192,6 +192,53 @@ describe('Parse Query', () => { }); }); + it('can do containedBy queries with numbers', async () => { + const NumberSet = Parse.Object.extend('NumberSet'); + const objectsList = []; + objectsList.push(new NumberSet({ numbers: [0, 1, 2] })); + objectsList.push(new NumberSet({ numbers: [2, 0] })); + objectsList.push(new NumberSet({ numbers: [1, 2, 3, 4] })); + + await Parse.Object.saveAll(objectsList); + + const query = new Parse.Query(NumberSet); + query.containedBy('numbers', [1, 2, 3, 4, 5]); + const results = await query.find(); + assert.equal(results.length, 1); + }); + + it('can do containedBy queries with pointer', async () => { + const objects = Array.from(Array(10).keys()).map((idx) => { + const obj = new Parse.Object('Object'); + obj.set('key', idx); + return obj; + }); + + const parent1 = new Parse.Object('Parent'); + const parent2 = new Parse.Object('Parent'); + const parent3 = new Parse.Object('Parent'); + + await Parse.Object.saveAll(objects); + + // [0, 1, 2] + parent1.set('objects', objects.slice(0, 3)); + + const shift = objects.shift(); + // [2, 0] + parent2.set('objects', [objects[1], shift]); + + // [1, 2, 3, 4] + parent3.set('objects', objects.slice(1, 4)); + + await Parse.Object.saveAll([parent1, parent2, parent3]); + const query = new Parse.Query('Parent'); + query.containedBy('objects', objects); + const results = await query.find(); + + assert.equal(results.length, 1); + assert.equal(results[0].id, parent3.id); + }); + it('can do equalTo queries', (done) => { let query = new Parse.Query('BoxedNumber'); query.equalTo('number', 3); diff --git a/src/ParseQuery.js b/src/ParseQuery.js index af74aedc7..714954d58 100644 --- a/src/ParseQuery.js +++ b/src/ParseQuery.js @@ -831,6 +831,17 @@ class ParseQuery { return this._addCondition(key, '$nin', value); } + /** + * Adds a constraint to the query that requires a particular key's value to + * be contained by the provided list of values. Get objects where all array elements match. + * @param {String} key The key to check. + * @param {Array} values The values that will match. + * @return {Parse.Query} Returns the query, so you can chain this call. + */ + containedBy(key: string, value: Array): ParseQuery { + return this._addCondition(key, '$containedBy', value); + } + /** * Adds a constraint to the query that requires a particular key's value to * contain each one of the provided list of values. diff --git a/src/__tests__/ParseQuery-test.js b/src/__tests__/ParseQuery-test.js index d2e7396ed..459933c67 100644 --- a/src/__tests__/ParseQuery-test.js +++ b/src/__tests__/ParseQuery-test.js @@ -263,6 +263,27 @@ describe('ParseQuery', () => { }); }); + it('can generate containedBy queries', () => { + const q = new ParseQuery('Item'); + q.containedBy('tags', ['hot', 'sold-out']); + expect(q.toJSON()).toEqual({ + where: { + tags: { + $containedBy: ['hot', 'sold-out'] + }, + }, + }); + + q.containedBy('tags', ['sale', 'new']); + expect(q.toJSON()).toEqual({ + where: { + tags: { + $containedBy: ['sale', 'new'] + }, + }, + }); + }); + it('can generate contains-all-starting-with queries', () => { var q = new ParseQuery('Item'); q.containsAllStartingWith('tags', ['ho', 'out']);