implemented added filters
This commit is contained in:
		@@ -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