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