Make notEqual work on relations

*  regression tests for #1349

* 🎉 fixes #1349

* Adds support for multiple constraints on the same key
This commit is contained in:
Florent Vilmart
2016-04-04 14:05:03 -04:00
committed by Drew
parent 89df778ac8
commit 0e3636d880
2 changed files with 168 additions and 12 deletions

View File

@@ -444,26 +444,60 @@ DatabaseController.prototype.reduceInRelation = function(className, query, schem
}
let promises = Object.keys(query).map((key) => {
if (query[key] && (query[key]['$in'] || query[key].__type == 'Pointer')) {
if (query[key] && (query[key]['$in'] || query[key]['$ne'] || query[key]['$nin'] || query[key].__type == 'Pointer')) {
let t = schema.getExpectedType(className, key);
let match = t ? t.match(/^relation<(.*)>$/) : false;
if (!match) {
return Promise.resolve(query);
}
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];
this.addInObjectIdsIds(ids, query);
return Promise.resolve(query);
// Build the list of queries
let queries = Object.keys(query[key]).map((constraintKey) => {
let relatedIds;
let isNegation = false;
if (constraintKey === 'objectId') {
relatedIds = [query[key].objectId];
} else if (constraintKey == '$in') {
relatedIds = query[key]['$in'].map(r => r.objectId);
} else if (constraintKey == '$nin') {
isNegation = true;
relatedIds = query[key]['$nin'].map(r => r.objectId);
} else if (constraintKey == '$ne') {
isNegation = true;
relatedIds = [query[key]['$ne'].objectId];
} else {
return;
}
return {
isNegation,
relatedIds
}
});
// remove the current queryKey as we don,t need it anymore
delete query[key];
// execute each query independnently to build the list of
// $in / $nin
let promises = queries.map((q) => {
if (!q) {
return Promise.resolve();
}
return this.owningIds(className, key, q.relatedIds).then((ids) => {
if (q.isNegation) {
this.addNotInObjectIdsIds(ids, query);
} else {
this.addInObjectIdsIds(ids, query);
}
return Promise.resolve();
});
});
return Promise.all(promises).then(() => {
return Promise.resolve();
})
}
return Promise.resolve(query);
return Promise.resolve();
})
return Promise.all(promises).then(() => {
@@ -520,6 +554,29 @@ DatabaseController.prototype.addInObjectIdsIds = function(ids = null, query) {
return query;
}
DatabaseController.prototype.addNotInObjectIdsIds = function(ids = null, query) {
let idsFromNin = query.objectId && query.objectId['$nin'] ? query.objectId['$nin'] : null;
let allIds = [idsFromNin, ids].filter(list => list !== null);
let totalLength = allIds.reduce((memo, list) => memo + list.length, 0);
let idsIntersection = [];
if (totalLength > 125) {
idsIntersection = intersect.big(allIds);
} else {
idsIntersection = intersect(allIds);
}
// Need to make sure we don't clobber existing $lt or other constraints on objectId.
// Clobbering $eq, $in and shorthand $eq (query.objectId === 'string') constraints
// is expected though.
if (!('objectId' in query) || typeof query.objectId === 'string') {
query.objectId = {};
}
query.objectId['$nin'] = idsIntersection;
return query;
}
// Runs a query on the database.
// Returns a promise that resolves to a list of items.
// Options: