Skip to content

Commit

Permalink
feat(adapter-commons): Added mongoDB like search in embedded objects
Browse files Browse the repository at this point in the history
  • Loading branch information
mhillerstrom authored Mar 31, 2021
1 parent 827cc9b commit 687e3c7
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 5 deletions.
29 changes: 24 additions & 5 deletions packages/adapter-commons/src/sort.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,36 @@ export function compare (a: any, b: any, compareStrings: any = exports.compareNS
// An in-memory sorting function according to the
// $sort special query parameter
export function sorter ($sort: any) {
const criteria = Object.keys($sort).map(key => {
const direction = $sort[key];
let sortLevels = false; // True if $sort has tags with '.' i.e. '{a: 1, b: -1, "c.x.z": 1}'

const getVal = (a: any, sortKeys: any[]) => {
let keys = sortKeys.map(key => key);
let val = a;
do {
let key = keys.shift();
val = val[key];
} while (keys.length);

return val;
};

const criteria = Object.keys($sort).map(key => {
const direction = $sort[key];
const keys = key.split('.');
sortLevels = keys.length > 1;

return { key, direction };
});
return { keys, direction };
});

return function (a: any, b: any) {
let compare;

for (const criterion of criteria) {
compare = criterion.direction * exports.compare(a[criterion.key], b[criterion.key]);
if (sortLevels) {
compare = criterion.direction * exports.compare(getVal(a, criterion.keys), getVal(b, criterion.keys));
} else {
compare = criterion.direction * exports.compare(a[criterion.keys[0]], b[criterion.keys[0]]);
}

if (compare !== 0) {
return compare;
Expand Down
65 changes: 65 additions & 0 deletions packages/adapter-commons/test/sort.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,4 +176,69 @@ describe('@feathersjs/adapter-commons', () => {
]);
});
});

describe('sorter mongoDB-like sorting on embedded objects', () => {
let data: any[] = [];

beforeEach(() => {
data = [
{ _id: 1, item: { category: "cake", type: "chiffon" }, amount: 10 },
{ _id: 2, item: { category: "cookies", type: "chocolate chip" }, amount: 50 },
{ _id: 3, item: { category: "cookies", type: "chocolate chip" }, amount: 15 },
{ _id: 4, item: { category: "cake", type: "lemon" }, amount: 30 },
{ _id: 5, item: { category: "cake", type: "carrot" }, amount: 20 },
{ _id: 6, item: { category: "brownies", type: "blondie" }, amount: 10 }
];

});

it('straight test', () => {
const sort = sorter({
amount: -1
});

assert.deepStrictEqual(data.sort(sort), [
{ _id: 2, item: { category: "cookies", type: "chocolate chip" }, amount: 50 },
{ _id: 4, item: { category: "cake", type: "lemon" }, amount: 30 },
{ _id: 5, item: { category: "cake", type: "carrot" }, amount: 20 },
{ _id: 3, item: { category: "cookies", type: "chocolate chip" }, amount: 15 },
{ _id: 1, item: { category: "cake", type: "chiffon" }, amount: 10 },
{ _id: 6, item: { category: "brownies", type: "blondie" }, amount: 10 }
]);
});

it('embedded sort 1', () => {
const sort = sorter({
"item.category": 1,
"item.type": 1,
});

assert.deepStrictEqual(data.sort(sort), [
{ _id: 6, item: { category: "brownies", type: "blondie" }, amount: 10 },
{ _id: 5, item: { category: "cake", type: "carrot" }, amount: 20 },
{ _id: 1, item: { category: "cake", type: "chiffon" }, amount: 10 },
{ _id: 4, item: { category: "cake", type: "lemon" }, amount: 30 },
{ _id: 2, item: { category: "cookies", type: "chocolate chip" }, amount: 50 },
{ _id: 3, item: { category: "cookies", type: "chocolate chip" }, amount: 15 }
]);
});

it('embedded sort 2', () => {
const sort = sorter({
"item.category": 1,
"item.type": 1,
amount: 1
});

assert.deepStrictEqual(data.sort(sort), [
{ _id: 6, item: { category: "brownies", type: "blondie" }, amount: 10 },
{ _id: 5, item: { category: "cake", type: "carrot" }, amount: 20 },
{ _id: 1, item: { category: "cake", type: "chiffon" }, amount: 10 },
{ _id: 4, item: { category: "cake", type: "lemon" }, amount: 30 },
{ _id: 3, item: { category: "cookies", type: "chocolate chip" }, amount: 15 },
{ _id: 2, item: { category: "cookies", type: "chocolate chip" }, amount: 50 }
]);
});
});

});

0 comments on commit 687e3c7

Please # to comment.