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:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user