Skip to content

Commit

Permalink
(#8491) - Fix $regex and $ne within $or operator
Browse files Browse the repository at this point in the history
  • Loading branch information
filionf committed Aug 22, 2022
1 parent bbeb7e5 commit 3fe71b0
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 18 deletions.
50 changes: 33 additions & 17 deletions packages/node_modules/pouchdb-selector-core/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,14 @@ function isAndInSelector(obj, isAnd) {
//
function massageSelector(input) {
var result = clone(input);
var wasAnded = false;
//#7458: if $and is present in selector (at any level) merge nested $and
if (isAndInSelector(result, false)) {
result = mergeAndedSelectorsNested(result);
if ('$and' in result) {
result = mergeAndedSelectors(result['$and']);
}
wasAnded = true;

//#7458: if $and is present in selector (at any level) merge nested $and
if (isAndInSelector(result, false)) {
result = mergeAndedSelectorsNested(result);
if ('$and' in result) {
result = mergeAndedSelectors(result['$and']);
}
}

['$or', '$nor'].forEach(function (orOrNor) {
if (orOrNor in result) {
Expand Down Expand Up @@ -308,22 +307,39 @@ function massageSelector(input) {

if (typeof matcher !== 'object' || matcher === null) {
matcher = {$eq: matcher};
} else if (!wasAnded) {
// These values must be placed in an array because these operators can be used multiple times on the same field
// when $and is used, mergeAndedSelectors takes care of putting them into arrays, otherwise it's done here:
if ('$ne' in matcher) {
matcher.$ne = [matcher.$ne];
}
if ('$regex' in matcher) {
matcher.$regex = [matcher.$regex];
}
}
result[field] = matcher;
}

normalizeArrayOperators(result);

return result;
}

//
// The $ne and $regex values must be placed in an array because these operators can be used multiple times on the same field.
// When $and is used, mergeAndedSelectors takes care of putting some of them into arrays, otherwise it's done here.
//
function normalizeArrayOperators(selector) {
Object.keys(selector).forEach(function (field) {
var matcher = selector[field];

if (Array.isArray(matcher)) {
matcher.forEach(function (matcherItem) {
if (matcherItem && typeof matcherItem === 'object') {
normalizeArrayOperators(matcherItem);
}
});
} else if (field === '$ne') {
selector.$ne = [matcher];
} else if (field === '$regex') {
selector.$regex = [matcher];
} else if (matcher && typeof matcher === 'object') {
normalizeArrayOperators(matcher);
}
});
}

export {
massageSelector,
isCombinationalField,
Expand Down
27 changes: 26 additions & 1 deletion tests/find/test-suite-1/test.regex.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ describe('test.regex.js', function () {
});
});

it('should works with index on multiple fields', function () {
it('should work with index on multiple fields', function () {
var db = context.db;
var index = {
"index": {
Expand All @@ -153,6 +153,7 @@ describe('test.regex.js', function () {
});
});
});

it('should works with $and with multiple $regex conditions on same field', function () {
var db = context.db;
var index = {
Expand Down Expand Up @@ -184,4 +185,28 @@ describe('test.regex.js', function () {
});
});
});

it('should find records within a simple $or condition', function () {
var db = context.db;
return db.find({
selector: {
$or: [
{ name: { $regex: 'Captain Falcon' } },
{ name: { $regex: 'Link' } },
]
}
}).then(function (resp) {
var docs = resp.docs.map(function (doc) {
delete doc._rev;
return doc;
});
docs.should.deep.equal([
{
name: 'Captain Falcon', _id: 'falcon', rank: 4, series: 'F-Zero', debut: 1990,
awesome: true
},
{ name: 'Link', rank: 10, _id: 'link', series: 'Zelda', debut: 1986, awesome: true },
]);
});
});
});

0 comments on commit 3fe71b0

Please sign in to comment.