Archived
2

implemented added filters

This commit is contained in:
VLE2FE 2020-07-10 13:09:15 +02:00
parent 523b2c9b68
commit 758eb0e143
3 changed files with 78 additions and 10 deletions

View File

@ -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

View File

@ -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');
}

View File

@ -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);
}