Skip to content

Commit ceb34c5

Browse files
authored
Support nor Query (#634)
* nor * doc fix
1 parent 4fd73b0 commit ceb34c5

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

integration/test/ParseQueryTest.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1454,6 +1454,55 @@ describe('Parse Query', () => {
14541454
}).catch(e => console.log(e));
14551455
});
14561456

1457+
it('can build NOR queries', async () => {
1458+
const objects = [];
1459+
for (let i = 0; i < 10; i += 1) {
1460+
const obj = new Parse.Object('NORTest');
1461+
obj.set({ x: i });
1462+
objects.push(obj);
1463+
}
1464+
await Parse.Object.saveAll(objects);
1465+
1466+
const q1 = new Parse.Query('NORTest');
1467+
q1.greaterThan('x', 5);
1468+
const q2 = new Parse.Query('NORTest');
1469+
q2.lessThan('x', 3);
1470+
const norQuery = Parse.Query.nor(q1, q2);
1471+
const results = await norQuery.find();
1472+
1473+
assert.equal(results.length, 3);
1474+
results.forEach((number) => {
1475+
assert(number.get('x') >= 3 && number.get('x') <= 5);
1476+
});
1477+
});
1478+
1479+
it('can build complex NOR queries', async () => {
1480+
const objects = [];
1481+
for (let i = 0; i < 10; i += 1) {
1482+
const child = new Parse.Object('Child');
1483+
child.set('x', i);
1484+
const parent = new Parse.Object('Parent');
1485+
parent.set('child', child);
1486+
parent.set('y', i);
1487+
objects.push(parent);
1488+
}
1489+
await Parse.Object.saveAll(objects);
1490+
1491+
const subQuery = new Parse.Query('Child');
1492+
subQuery.equalTo('x', 4);
1493+
const q1 = new Parse.Query('Parent');
1494+
q1.matchesQuery('child', subQuery);
1495+
const q2 = new Parse.Query('Parent');
1496+
q2.equalTo('y', 5);
1497+
const norQuery = new Parse.Query.nor(q1, q2);
1498+
const results = await norQuery.find();
1499+
1500+
assert.equal(results.length, 8);
1501+
results.forEach((number) => {
1502+
assert(number.get('x') !== 4 || number.get('x') !== 5);
1503+
});
1504+
});
1505+
14571506
it('can iterate over results with each', (done) => {
14581507
let items = [];
14591508
for (let i = 0; i < 50; i++) {

src/ParseQuery.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ class ParseQuery {
237237

238238
/**
239239
* Adds constraint that all of the passed in queries match.
240-
* @method _andQuery
241240
* @param {Array} queries
242241
* @return {Parse.Query} Returns the query, so you can chain this call.
243242
*/
@@ -250,6 +249,20 @@ class ParseQuery {
250249
return this;
251250
}
252251

252+
/**
253+
* Adds constraint that none of the passed in queries match.
254+
* @param {Array} queries
255+
* @return {Parse.Query} Returns the query, so you can chain this call.
256+
*/
257+
_norQuery(queries: Array<ParseQuery>): ParseQuery {
258+
var queryJSON = queries.map((q) => {
259+
return q.toJSON().where;
260+
});
261+
262+
this._where.$nor = queryJSON;
263+
return this;
264+
}
265+
253266
/**
254267
* Helper for condition queries
255268
*/
@@ -1422,6 +1435,24 @@ class ParseQuery {
14221435
query._andQuery(queries);
14231436
return query;
14241437
}
1438+
1439+
/**
1440+
* Constructs a Parse.Query that is the NOR of the passed in queries. For
1441+
* example:
1442+
* <pre>const compoundQuery = Parse.Query.nor(query1, query2, query3);</pre>
1443+
*
1444+
* will create a compoundQuery that is a nor of the query1, query2, and
1445+
* query3.
1446+
* @param {...Parse.Query} var_args The list of queries to NOR.
1447+
* @static
1448+
* @return {Parse.Query} The query that is the NOR of the passed in queries.
1449+
*/
1450+
static nor(...queries: Array<ParseQuery>): ParseQuery {
1451+
const className = _getClassNameFromQueries(queries);
1452+
const query = new ParseQuery(className);
1453+
query._norQuery(queries);
1454+
return query;
1455+
}
14251456
}
14261457

14271458
var DefaultController = {

src/__tests__/ParseQuery-test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,40 @@ describe('ParseQuery', () => {
10351035
});
10361036
});
10371037

1038+
it('can combine queries with a NOR clause', () => {
1039+
const q = new ParseQuery('Item');
1040+
let q2 = new ParseQuery('Purchase');
1041+
expect(ParseQuery.nor.bind(null, q, q2)).toThrow(
1042+
'All queries must be for the same class.',
1043+
);
1044+
1045+
q2 = new ParseQuery('Item');
1046+
q.equalTo('size', 'medium');
1047+
q2.equalTo('size', 'large');
1048+
1049+
let mediumOrLarge = ParseQuery.nor(q, q2);
1050+
expect(mediumOrLarge.toJSON()).toEqual({
1051+
where: {
1052+
$nor: [
1053+
{ size: 'medium' },
1054+
{ size: 'large' },
1055+
],
1056+
},
1057+
});
1058+
1059+
// It removes limits, skips, etc
1060+
q.limit(10);
1061+
mediumOrLarge = ParseQuery.nor(q, q2);
1062+
expect(mediumOrLarge.toJSON()).toEqual({
1063+
where: {
1064+
$nor: [
1065+
{ size: 'medium' },
1066+
{ size: 'large' },
1067+
],
1068+
},
1069+
});
1070+
});
1071+
10381072
it('can get the first object of a query', (done) => {
10391073
CoreManager.setQueryController({
10401074
aggregate() {},

0 commit comments

Comments
 (0)