switched to aggregation, included material sort keys
This commit is contained in:
parent
43413001e9
commit
8aa051f0bd
@ -230,6 +230,20 @@ describe('/sample', () => {
|
|||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
it('sorts the samples correctly for material keys', done => {
|
||||||
|
TestHelper.request(server, done, {
|
||||||
|
method: 'get',
|
||||||
|
url: '/samples?status=all&sort=material.name-desc',
|
||||||
|
auth: {basic: 'janedoe'},
|
||||||
|
httpStatus: 200
|
||||||
|
}).end((err, res) => {
|
||||||
|
if (err) return done(err);
|
||||||
|
should(res.body[0]).have.property('_id', '400000000000000000000002');
|
||||||
|
should(res.body[1]).have.property('_id', '400000000000000000000006');
|
||||||
|
should(res.body[2]).have.property('_id', '400000000000000000000001');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
it('rejects a negative page size', done => {
|
it('rejects a negative page size', done => {
|
||||||
TestHelper.request(server, done, {
|
TestHelper.request(server, done, {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
@ -25,65 +25,69 @@ router.get('/samples', async (req, res, next) => {
|
|||||||
const {error, value: filters} = SampleValidate.query(req.query);
|
const {error, value: filters} = SampleValidate.query(req.query);
|
||||||
if (error) return res400(error, res);
|
if (error) return res400(error, res);
|
||||||
|
|
||||||
let status;
|
const query = [];
|
||||||
|
query.push({$match: {$and: []}});
|
||||||
if (filters.hasOwnProperty('status')) {
|
if (filters.hasOwnProperty('status')) {
|
||||||
if(filters.status === 'all') {
|
if(filters.status === 'all') {
|
||||||
status = {$or: [{status: globals.status.validated}, {status: globals.status.new}]}
|
query[0].$match.$and.push({$or: [{status: globals.status.validated}, {status: globals.status.new}]});
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
status = {status: globals.status[filters.status]};
|
query[0].$match.$and.push({status: globals.status[filters.status]});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // default
|
else { // default
|
||||||
status = {status: globals.status.validated};
|
query[0].$match.$and.push({status: globals.status.validated});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const sort = [];
|
|
||||||
let paging = {}
|
|
||||||
|
|
||||||
// sorting
|
// sorting
|
||||||
filters.sort = filters.sort.split('-');
|
filters.sort = filters.sort.split('-');
|
||||||
filters.sort[0] = filters.sort[0] === 'added' ? '_id' : filters.sort[0]; // route added sorting criteria to _id
|
filters.sort[0] = filters.sort[0] === 'added' ? '_id' : filters.sort[0]; // route added sorting criteria to _id
|
||||||
filters.sort[1] = filters.sort[1] === 'desc' ? -1 : 1;
|
filters.sort[1] = filters.sort[1] === 'desc' ? -1 : 1;
|
||||||
|
|
||||||
if (!filters['to-page']) { // set to-page default
|
if (!filters['to-page']) { // set to-page default
|
||||||
filters['to-page'] = 0;
|
filters['to-page'] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filters.sort[0].indexOf('material.') >= 0) { // need to populate materials, material supplier and group
|
||||||
|
query.push(
|
||||||
|
{$lookup: {from: 'materials', localField: 'material_id', foreignField: '_id', as: 'material'}},
|
||||||
|
{$set: {material: { $arrayElemAt: ['$material', 0]}}},
|
||||||
|
{$lookup: { from: 'material_groups', localField: 'material.group_id', foreignField: '_id', as: 'material.group' }},
|
||||||
|
{$set: {'material.group': { $arrayElemAt: ['$material.group.name', 0]}}},
|
||||||
|
{$lookup: { from: 'material_suppliers', localField: 'material.supplier_id', foreignField: '_id', as: 'material.supplier'}},
|
||||||
|
{$set: {'material.supplier': {$arrayElemAt: ['$material.supplier.name', 0]}}}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (filters['from-id']) { // from-id specified
|
if (filters['from-id']) { // from-id specified
|
||||||
const fromSample = SampleValidate.output(await SampleModel.findById(filters['from-id']).lean().exec().catch(err => {next(err);}));
|
const fromSample = await SampleModel.findById(filters['from-id']).lean().exec().catch(err => {next(err);});
|
||||||
if (fromSample instanceof Error) return;
|
if (fromSample instanceof Error) return;
|
||||||
|
|
||||||
if ((filters['to-page'] === 0 && filters.sort[1] === 1) || (filters.sort[1] * filters['to-page'] > 0)) { // asc
|
if ((filters['to-page'] === 0 && filters.sort[1] === 1) || (filters.sort[1] * filters['to-page'] > 0)) { // asc
|
||||||
paging = {$or: [{[filters.sort[0]]: {$gt: fromSample[filters.sort[0]]}}, {$and: [{[filters.sort[0]]: fromSample[filters.sort[0]]}, {_id: {$gte: mongoose.Types.ObjectId(filters['from-id'])}}]}]};
|
query[0].$match.$and.push({$or: [{[filters.sort[0]]: {$gt: fromSample[filters.sort[0]]}}, {$and: [{[filters.sort[0]]: fromSample[filters.sort[0]]}, {_id: {$gte: new mongoose.Types.ObjectId(filters['from-id'])}}]}]});
|
||||||
sort.push([filters.sort[0], 1]);
|
query.push({$sort: {[filters.sort[0]]: 1, _id: 1}});
|
||||||
sort.push(['_id', 1]);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
paging = {$or: [{[filters.sort[0]]: {$lt: fromSample[filters.sort[0]]}}, {$and: [{[filters.sort[0]]: fromSample[filters.sort[0]]}, {_id: {$lte: mongoose.Types.ObjectId(filters['from-id'])}}]}]};
|
query[0].$match.$and.push({$or: [{[filters.sort[0]]: {$lt: fromSample[filters.sort[0]]}}, {$and: [{[filters.sort[0]]: fromSample[filters.sort[0]]}, {_id: {$lte: new mongoose.Types.ObjectId(filters['from-id'])}}]}]});
|
||||||
sort.push([filters.sort[0], -1]);
|
query.push({$sort: {[filters.sort[0]]: -1, _id: -1}});
|
||||||
sort.push(['_id', -1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { // sort from beginning
|
else { // sort from beginning
|
||||||
sort.push([filters.sort[0], filters.sort[1]]); // set _id as secondary sort
|
query.push({$sort: {[filters.sort[0]]: filters.sort[1], '_id': filters.sort[1]}}); // set _id as secondary sort
|
||||||
sort.push(['_id', filters.sort[1]]); // set _id as secondary sort
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = SampleModel.find({$and: [status, paging]});
|
if (filters.sort[0].indexOf('material.') >= 0) { // unpopulate materials again
|
||||||
|
query.push({$unset: 'material'});
|
||||||
if (filters['page-size']) {
|
|
||||||
query.limit(filters['page-size']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filters['to-page']) {
|
if (filters['to-page']) {
|
||||||
query.skip(Math.abs(filters['to-page'] + Number(filters['to-page'] < 0)) * filters['page-size'] + Number(filters['to-page'] < 0));
|
query.push({$skip: Math.abs(filters['to-page'] + Number(filters['to-page'] < 0)) * filters['page-size'] + Number(filters['to-page'] < 0)}) // number to skip, if going back pages, one page has to be skipped less but on sample more
|
||||||
}
|
}
|
||||||
|
|
||||||
query.sort(sort);
|
if (filters['page-size']) {
|
||||||
|
query.push({$limit: filters['page-size']});
|
||||||
|
}
|
||||||
|
|
||||||
query.lean().exec((err, data) => {
|
SampleModel.aggregate(query).exec((err, data) => {
|
||||||
if (err) return next(err);
|
if (err) return next(err);
|
||||||
if (filters['to-page'] < 0) {
|
if (filters['to-page'] < 0) {
|
||||||
data.reverse();
|
data.reverse();
|
||||||
|
@ -133,7 +133,7 @@ export default class SampleValidate {
|
|||||||
'from-id': IdValidate.get(),
|
'from-id': IdValidate.get(),
|
||||||
'to-page': Joi.number().integer(),
|
'to-page': Joi.number().integer(),
|
||||||
'page-size': Joi.number().integer().min(1),
|
'page-size': Joi.number().integer().min(1),
|
||||||
sort: Joi.string().pattern(/^(_id|color|number|type|batch|added)-(asc|desc)$/m).default('_id-asc') // TODO: material keys
|
sort: Joi.string().pattern(/^(_id|color|number|type|batch|added|material\.name|material\.supplier|material\.group|material\.mineral|material\.glass_fiber|material\.carbon_fiber)-(asc|desc)$/m).default('_id-asc') // TODO: material keys
|
||||||
}).with('to-page', 'page-size').validate(data);
|
}).with('to-page', 'page-size').validate(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user