Home > Software engineering >  How to write a chain of methods in JS with a mapping function
How to write a chain of methods in JS with a mapping function

Time:04-12

Context

I'm using knex.js, a SQL query builder. This question is not specific about knex.js though but about javascript semantics, so knex.js is just here to illustrate my problem. So I build SQL queries with knex.js by just chaining methods.

For instance, to get contacts in a table:

const getContacts = await knex
  .select('*')
  .from('contacts')
  .where({age: 21}) // Filters contacts that have age 21
  .andWhere({name: 'Bob'}) // Filters contacts that are named Bob
  .andWhere({eyeColor: 'blue'}) // ...you got the idea
  ...

Question

I want to make a function that given an array of filters, returns the built query to get the right set of contacts. I can theoretically put as many .andWhere that I want so I'd like do declare that with a map over the input array or something like that, i.e

const getContactsQuery = (filterArray) => (
  knex
    .select('*')
    .from('contacts')
    .where(filterArray[0])
    .andWhere(filterArray[1])
    ...
    .andWhere(filterArray[filterArray.length - 1])
)

The question: Is there any way I can build this chain of .andWhere mapping over filterArray?

Things I've tried

Using reduce this way

const getContactsQuery = (filterArray) => (
  filterArray.reduce((acc, filterElement, index) => {
    if(index === 0) {
      return acc.where(filterElement)
    }
    return acc.andWhere(filterElement)
  },
  knex.select('*').from('contacts')
  )
)

This may not work because this would get knex to fetch the table elements at each iteration of the reduce.

EDIT: It should actually work for knex because "knex does not query the database unless you await the last chaining". So this is solved for my context but there eventually could be other use cases where this would not work, don't know

  • Related