implemented added filters
This commit is contained in:
parent
523b2c9b68
commit
758eb0e143
@ -7,7 +7,7 @@ import ChangelogModel from './models/changelog';
|
||||
// database urls, prod db url is retrieved automatically
|
||||
const TESTING_URL = 'mongodb://localhost/dfopdb_test';
|
||||
const DEV_URL = 'mongodb://localhost/dfopdb';
|
||||
const debugging = false;
|
||||
const debugging = true;
|
||||
|
||||
if (process.env.NODE_ENV !== 'production' && debugging) {
|
||||
mongoose.set('debug', true); // enable mongoose debug
|
||||
|
@ -43,6 +43,54 @@ router.get('/samples', async (req, res, next) => {
|
||||
if (!filters['to-page']) { // set to-page default
|
||||
filters['to-page'] = 0;
|
||||
}
|
||||
const addedFilter = filters.filters.find(e => e.field === 'added');
|
||||
if (addedFilter) { // convert added filter to object id
|
||||
filters.filters.splice(filters.filters.findIndex(e => e.field === 'added'), 1);
|
||||
if (addedFilter.mode === 'in') {
|
||||
const v = []; // query value
|
||||
addedFilter.values.forEach(value => {
|
||||
const date = [new Date(value).setHours(0,0,0,0), new Date(value).setHours(23,59,59,999)];
|
||||
v.push({$and: [{ _id: { '$gte': dateToOId(date[0])}}, { _id: { '$lte': dateToOId(date[1])}}]});
|
||||
});
|
||||
filters.filters.push({mode: 'or', field: '_id', values: v});
|
||||
}
|
||||
else if (addedFilter.mode === 'nin') {
|
||||
addedFilter.values = addedFilter.values.sort();
|
||||
const v = []; // query value
|
||||
|
||||
for (let i = 0; i <= addedFilter.values.length; i ++) {
|
||||
v[i] = {$and: []};
|
||||
if (i > 0) {
|
||||
const date = new Date(addedFilter.values[i - 1]).setHours(23,59,59,999);
|
||||
v[i].$and.push({ _id: { '$gt': dateToOId(date)}}) ;
|
||||
}
|
||||
if (i < addedFilter.values.length) {
|
||||
const date = new Date(addedFilter.values[i]).setHours(0,0,0,0);
|
||||
v[i].$and.push({ _id: { '$lt': dateToOId(date)}}) ;
|
||||
}
|
||||
}
|
||||
filters.filters.push({mode: 'or', field: '_id', values: v});
|
||||
}
|
||||
else {
|
||||
// start and end of day
|
||||
const date = [new Date(addedFilter.values[0]).setHours(0,0,0,0), new Date(addedFilter.values[0]).setHours(23,59,59,999)];
|
||||
if (addedFilter.mode === 'lt') { // lt start
|
||||
filters.filters.push({mode: 'lt', field: '_id', values: [dateToOId(date[0])]});
|
||||
}
|
||||
if (addedFilter.mode === 'eq' || addedFilter.mode === 'lte') { // lte end
|
||||
filters.filters.push({mode: 'lte', field: '_id', values: [dateToOId(date[1])]});
|
||||
}
|
||||
if (addedFilter.mode === 'gt') { // gt end
|
||||
filters.filters.push({mode: 'gt', field: '_id', values: [dateToOId(date[1])]});
|
||||
}
|
||||
if (addedFilter.mode === 'eq' || addedFilter.mode === 'gte') { // gte start
|
||||
filters.filters.push({mode: 'gte', field: '_id', values: [dateToOId(date[0])]});
|
||||
}
|
||||
if (addedFilter.mode === 'ne') {
|
||||
filters.filters.push({mode: 'or', field: '_id', values: [{ _id: { '$lt': dateToOId(date[0])}}, { _id: { '$gt': dateToOId(date[1])}}]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const sortFilterKeys = filters.filters.map(e => e.field);
|
||||
|
||||
@ -80,7 +128,6 @@ router.get('/samples', async (req, res, next) => {
|
||||
{$addFields: {['sample.' + measurementName]: '$measurement.values'}}, // more restructuring
|
||||
{$replaceRoot: {newRoot: {$mergeObjects: [{$arrayElemAt: ['$sample', 0]}, {}]}}}
|
||||
);
|
||||
addFilterQueries(queryPtr, filters.filters.filter(e => sampleKeys.indexOf(e.field) >= 0)); // sample filters
|
||||
}
|
||||
else { // sorting with samples as starting collection
|
||||
collection = SampleModel;
|
||||
@ -568,13 +615,23 @@ module.exports = router;
|
||||
|
||||
async function numberGenerate (sample, req, res, next) { // generate number in format Location32, returns false on error
|
||||
const sampleData = await SampleModel
|
||||
.findOne({number: new RegExp('^' + req.authDetails.location + '[0-9]+$', 'm')})
|
||||
.sort({number: -1})
|
||||
.lean()
|
||||
// .findOne({number: new RegExp('^' + req.authDetails.location + '[0-9]+$', 'm')})
|
||||
// .sort({number: -1})
|
||||
// .lean()
|
||||
.aggregate([
|
||||
{$match: {number: new RegExp('^' + 'Rng' + '[0-9]+$', 'm')}},
|
||||
// {$addFields: {number2: {$toDecimal: {$arrayElemAt: [{$split: [{$arrayElemAt: [{$split: ['$number', 'Rng']}, 1]}, '_']}, 0]}}}}, // not working with MongoDb 3.6
|
||||
{$addFields: {sortNumber: {$let: {
|
||||
vars: {tmp: {$concat: ['000000000000000000000000000000', {$arrayElemAt: [{$split: [{$arrayElemAt: [{$split: ['$number', 'Rng']}, 1]}, '_']}, 0]}]}},
|
||||
in: {$substrCP: ['$$tmp', {$subtract: [{$strLenCP: '$$tmp'}, 30]}, {$strLenCP: '$$tmp'}]}
|
||||
}}}},
|
||||
{$sort: {sortNumber: -1}},
|
||||
{$limit: 1}
|
||||
])
|
||||
.exec()
|
||||
.catch(err => next(err));
|
||||
if (sampleData instanceof Error) return false;
|
||||
return req.authDetails.location + (sampleData ? Number(sampleData.number.replace(/[^0-9]+/g, '')) + 1 : 1);
|
||||
return req.authDetails.location + (sampleData[0] ? Number(sampleData[0].number.replace(/[^0-9]+/g, '')) + 1 : 1);
|
||||
}
|
||||
|
||||
async function numberCheck(sample, res, next) {
|
||||
@ -707,5 +764,16 @@ function addFilterQueries (queryPtr, filters) { // returns array of match queri
|
||||
}
|
||||
|
||||
function filterQueries (filters) {
|
||||
return filters.map(e => ({[e.field]: {['$' + e.mode]: (e.mode.indexOf('in') >= 0 ? e.values : e.values[0])}})) // add filter criteria as {field: {$mode: value}}, only use first value when mode is not in/nin
|
||||
return filters.map(e => {
|
||||
if (e.mode === 'or') { // allow or queries (needed for $ne added)
|
||||
return {['$' + e.mode]: e.values};
|
||||
}
|
||||
else {
|
||||
return {[e.field]: {['$' + e.mode]: (e.mode.indexOf('in') >= 0 ? e.values : e.values[0])}}; // add filter criteria as {field: {$mode: value}}, only use first value when mode is not in/nin
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function dateToOId (date) { // convert date to ObjectId
|
||||
return mongoose.Types.ObjectId(Math.floor(date / 1000).toString(16) + '0000000000000000');
|
||||
}
|
@ -175,7 +175,7 @@ export default class SampleValidate {
|
||||
let validator;
|
||||
let field = data.filters[i].field
|
||||
if (/material\./.test(field)) { // select right validation model
|
||||
validator = MaterialValidate.outputV();
|
||||
validator = MaterialValidate.outputV().append({number: Joi.string().max(128).allow('')});
|
||||
field = field.replace('material.', '');
|
||||
}
|
||||
else if (/measurements\./.test(field)) {
|
||||
@ -195,7 +195,7 @@ export default class SampleValidate {
|
||||
validator = Joi.object(this.sample);
|
||||
}
|
||||
const {value, error} = validator.validate({[field]: e});
|
||||
if (error) throw error; // reject invalid values
|
||||
if (error) throw error; // reject invalid values // TODO: return exact error description, handle in frontend filters
|
||||
return value[field];
|
||||
});
|
||||
}
|
||||
@ -215,7 +215,7 @@ export default class SampleValidate {
|
||||
filters: Joi.array().items(Joi.object({
|
||||
mode: Joi.string().valid('eq', 'ne', 'lt', 'lte', 'gt', 'gte', 'in', 'nin'),
|
||||
field: Joi.string().pattern(new RegExp('^(' + this.fieldKeys.join('|').replace(/\./g, '\\.').replace(/\*/g, '.+') + ')$', 'm')),
|
||||
values: Joi.array().items(Joi.alternatives().try(Joi.string().max(128), Joi.number(), Joi.boolean())).min(1)
|
||||
values: Joi.array().items(Joi.alternatives().try(Joi.string().max(128), Joi.number(), Joi.boolean(), Joi.date().iso())).min(1)
|
||||
})).default([])
|
||||
}).with('to-page', 'page-size').validate(data);
|
||||
}
|
||||
|
Reference in New Issue
Block a user