Home > Net >  How to create a dynamic query builder in javascript?
How to create a dynamic query builder in javascript?

Time:09-14

I had following data array which include the details of employees

const data = [{
  name: 'Foo',
  age: 32,
  emp_id: 19,
  role: 'Manager',
},
{
  name: 'Foo',
  age: 33,
  emp_id: 23,
  role: 'Developer',
}]

I need to perform array.find method to find the correct one,Problem is I had all the find criteria as array,

const criteria = [{
  operator: "equals",
  key: "name",
  value: "Foo"
}, {
  elementOperator: "AND",
  operator: "equals",
  key: "age",
  value: 32
}]

find query down below,

const filteredData = data.find(c => c.name === "Foo" && c.age === 32)

My question how to convert the criteria to query,

c.name === "Foo" && c.age === 32

CodePudding user response:

Don't judge me much, this is just a demo of the function dispatch approach. The use of elementOperator is not implemented here. But you can extend this approach to your own needs. I hope it helped.

Live Demo:

const data = [{name: 'Foo', age: 32, emp_id: 19, role: 'Developer'},
              {name: 'Goo', age: 33, emp_id: 20, role: 'Manager'},
              {name: 'Eva', age: 34, emp_id: 21, role: 'CTO'},
              {name: 'Roo', age: 35, emp_id: 22, role: 'QA'},
              {name: 'Too', age: 36, emp_id: 23, role: 'QA'},
              {name: 'Noo', age: 37, emp_id: 24, role: 'Developer'},
              {name: 'Moo', age: 38, emp_id: 25, role: 'Developer'}];

const myFilter = (data, criteria) => {
  const predicates = {
    equals: (key, value) => (obj) => obj[key] === value,
    gte: (key, value) => (obj) => obj[key] >= value,
    lte: (key, value) => (obj) => obj[key] <= value,
    localeCompare: (key, value) => (obj) => !obj[key].localeCompare(value, false, { sensitivity: 'base' }),
    includes: (key, value) => (obj) => obj[key].toLowerCase().includes(value.toLowerCase()),
  };

  return criteria.map(({ operator, key, value }) => predicates[operator](key, value))
    .reduce((acc, condition) => acc.filter(condition), data);
};


// --- TEST---
const criteriaToText = (criteria) => criteria
  .map(e =>`${e.key} ${e.operator} ${e.value}`)
  .join(', and ');

let criteria =  [{operator: "equals", key: "name", value: "Foo"}, {elementOperator: "AND", operator: "equals", key: "age", value: 32}];
console.log(criteriaToText(criteria));
console.log(myFilter(data, criteria));

criteria = [{operator: "gte", key: "age", value: 35},{operator: "equals", key: "role", value: "Developer"}];
console.log(criteriaToText(criteria));
console.log(myFilter(data, criteria));

criteria = [{operator: "lte", key: "age", value: 33}];
console.log(criteriaToText(criteria));
console.log(myFilter(data, criteria));

criteria = [{operator: "localeCompare", key: "name", value: "evä"}];
console.log(criteriaToText(criteria));
console.log(myFilter(data, criteria));

criteria = [{operator: "includes", key: "role", value: "er"},{operator: "lte", key: "age", value: 37},{operator: "gte", key: "emp_id", value: 19}];
console.log(criteriaToText(criteria));
console.log(myFilter(data, criteria));
.as-console-wrapper { max-height: 100% !important; top: 0 }

  • Related