Archived
2

switched to aggregation, included material sort keys

This commit is contained in:
VLE2FE 2020-06-26 15:23:29 +02:00
parent 43413001e9
commit 8aa051f0bd
3 changed files with 44 additions and 26 deletions

View File

@ -230,6 +230,20 @@ describe('/sample', () => {
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 => {
TestHelper.request(server, done, {
method: 'get',

View File

@ -25,65 +25,69 @@ router.get('/samples', async (req, res, next) => {
const {error, value: filters} = SampleValidate.query(req.query);
if (error) return res400(error, res);
let status;
const query = [];
query.push({$match: {$and: []}});
if (filters.hasOwnProperty('status')) {
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 {
status = {status: globals.status[filters.status]};
query[0].$match.$and.push({status: globals.status[filters.status]});
}
}
else { // default
status = {status: globals.status.validated};
query[0].$match.$and.push({status: globals.status.validated});
}
const sort = [];
let paging = {}
// sorting
filters.sort = filters.sort.split('-');
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;
if (!filters['to-page']) { // set to-page default
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
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 ((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'])}}]}]};
sort.push([filters.sort[0], 1]);
sort.push(['_id', 1]);
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'])}}]}]});
query.push({$sort: {[filters.sort[0]]: 1, _id: 1}});
}
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'])}}]}]};
sort.push([filters.sort[0], -1]);
sort.push(['_id', -1]);
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'])}}]}]});
query.push({$sort: {[filters.sort[0]]: -1, _id: -1}});
}
}
else { // sort from beginning
sort.push([filters.sort[0], filters.sort[1]]); // set _id as secondary sort
sort.push(['_id', 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
}
const query = SampleModel.find({$and: [status, paging]});
if (filters['page-size']) {
query.limit(filters['page-size']);
if (filters.sort[0].indexOf('material.') >= 0) { // unpopulate materials again
query.push({$unset: 'material'});
}
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 (filters['to-page'] < 0) {
data.reverse();

View File

@ -133,7 +133,7 @@ export default class SampleValidate {
'from-id': IdValidate.get(),
'to-page': Joi.number().integer(),
'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);
}
}