Использование условного фильтра Knex.js и SQL с несколькими критериями поиска

#javascript #sql #node.js #knex.js

#javascript #sql #node.js #knex.js

Вопрос:

У меня есть база данных элементов, которые мой пользователь должен иметь возможность искать. Они могут применять различные фильтры, такие как category , searchTerm , itemType .

Я знаю, как применить каждый из этих фильтров в запросе knex, но не уверен, как их условно объединить. Например. в одном случае пользователь вводит только searchTerm. Поэтому я не хочу фильтровать по категории или типу товара, а только по критерию поиска. Однако я хочу иметь только одну функцию knex, которая условно добавляет дополнительные предложения к запросу.

Что-то вроде:

 const getFilteredItems = (searchCriteria) => knex('items')
   // IF (searchCriteria.searchTerm)
  .where('items.itemName', 'like', `%${searchCriteria.searchTerm}%`)
  // IF (searchCriteria.itemType)
  .where('items.itemType', '=', searchCriteria.itemType)
  // IF (searchCriteria.category)
  .where('items.category', '=', searchCriteria.category)
  

Но я не уверен, как условно добавить дополнительные where предложения к запросу knex. Есть ли элегантный способ сделать это без написания необработанного SQL?

Ответ №1:

Вы можете условно построить свой запрос с помощью конструктора запросов knex:

 const getFilteredItems = (searchCriteria) => knex('items')
  .where((qb) => {
    if (searchCriteria.searchTerm) {
      qb.where('items.itemName', 'like', `%${searchCriteria.searchTerm}%`);
    }

    if (searchCriteria.itemType) {
      qb.orWhere('items.itemType', '=', searchCriteria.itemType);
    }

    if (searchCriteria.category) {
      qb.orWhere('items.category', '=', searchCriteria.category);
    }
  });
  

Вы также можете использовать this вместо принятия аргумента querybuilder, как в примере, приведенном @abdulbarik, но я думаю, что это менее явно.

Комментарии:

1. Обратите внимание, что функции со стрелками используют привязку родительской функции this . Если вы хотите использовать this вместо принятия параметра QueryBuilder, это должна быть обычная функция.

Ответ №2:

Вы можете попробовать следующее :

 const getFilteredItems = (searchCriteria) => knex('items')
  .where('items.itemName', 'like', `%${searchCriteria.searchTerm || ''}%`)
  .where('items.itemType', 'like', `%${searchCriteria.itemType || ''}%`)
  .where('items.category', 'like', `%${searchCriteria.category || ''}%`)
  

Если какой-либо параметр отсутствует или undefined , он будет соответствовать полю, которое будет похоже '%%' , что фактически означает, не заботьтесь об этом параметре.

Ответ №3:

Попробуйте orWhere и обновите свой запрос на этой основе

 const getFilteredItems = (searchCriteria) => knex('items')
   // IF (searchCriteria.searchTerm)
  .where('items.itemName', 'like', `%${searchCriteria.searchTerm}%`)
  // IF (searchCriteria.itemType)
  .orWhere('items.itemType', '=', searchCriteria.itemType)
  // IF (searchCriteria.category)
  .orWhere('items.category', '=', searchCriteria.category)
  

Пример

 knex('users').where(function() {
  this.where('id', 1).orWhere('id', '>', 10)
}).orWhere({name: 'Tester'})
  

Ответ №4:

Вы можете упростить это с помощью функции async await, подобной этой:

 public async getFilteredItems(searchCriteria): Promise<any[]> {
    const table = 'items';
    const columns = ['itemName', 'itemType', 'category'];
    const qb = (query) => {
      for (const col of columns) {
        query.orWhere(`${table}.${col}`, 'like', `%${searchCriteria[col]}%`);
      }
    }
    return await knex(table).where(qb);
}