Как создать функцию динамического запроса в модуле nodejs pg?

Например:

const update = ({title, price, imageUrl, description, whereId, whereTitle }) => {
    return db.query(
        `UPDATE products 
            SET title=$1, 
                price=$2,
                "imageUrl"=$3,
                description=$4 
            WHERE 
                id=$5,
                title ILIKE '%$6%'
            `,
        [title, price, imageUrl, description, whereId, whereTitle],
    )
}

update({
    whereId: 1,
    title: 'Aliens 2: Electric Boogaloo',
    description: 'Best sequel ever',
})
// shall execute this query:
// UPDATE products SET title='Aliens 2: Electric Boogaloo', description'Best sequel ever' WHERE id=1
// and keeping the price, "imageUrl" untouched / previous value

update({
    whereTitle: 'godfather',
    price: 20,
})
// shall execute this query:
// UPDATE products SET price=20 WHERE title ILIKE '%godfather%'
// or set the price of every products that contain the word 'godfather' as $20
// and keeping the title, "imageUrl", description, id untouched / previous value

Прямо сейчас мне нужно создать запрос для каждого возможного запроса

  • УСТАНОВИТЬ заголовок ГДЕ id

  • УСТАНОВИТЬ название, цену ГДЕ id

  • УСТАНОВИТЕ цену, "imageUrl" ГДЕ название

  • ...

Это не очень сухой, поэтому я думаю, что должен быть лучший способ сделать это

Изменить 1:

Вот так, я предполагаю, будет выглядеть код.

db.query(
    `UPDATE products 
        SET 
            title !== null? "title=$1," : skipToNextLine() 
            price !== null? "price=$2," : skipToNextLine()
            "imageUrl" !== null? "\"imageUrl\"=$3," : skipToNextLine()
            description !== null? "description=$4"  : skipToNextLine()
        whereId !== null && whereTitle !== null? "WHERE" : skipToNextLine()
            whereId !== null? "id=$5," : skipToNextLine()
            whereTitle !== null? "title ILIKE '%$6%'" : skipToNextLine()
        `,
    [title, price, imageUrl, description, whereId, whereTitle],
)

Я делаю это в стиле троичного выражения, но есть много других стилей. Я думаю, что идея похожа на язык шаблонов html, такой как pug.js, ejs, handlebars и т. Д. Должен быть другой способ, кроме написания десятков статических html-файлов для вашего html.

Изменить 2:

Я использовал конкатенацию строк для быстрого и грязного решения, но мне интересно, уязвимо ли оно для SQL-инъекции. Код также становится очень длинным, а надежность / простота понимания кода значительно снижается.

Вот мое текущее решение:

const update = ({
    title,
    price,
    imageUrl,
    description,
    whereId,
    whereTitle,
}) => {
    let queryText = 'UPDATE products SET'
    let queryValue = []
    let dollarCounter = 1
    if (!!title) {
        queryText = queryText.concat(` title=$${dollarCounter},`)
        queryValue.push(title)
        dollarCounter++
    }
    if (!!price) {
        queryText = queryText.concat(` price=$${dollarCounter},`)
        queryValue.push(price)
        dollarCounter++
    }
    if (!!imageUrl) {
        queryText = queryText.concat(` "imageUrl"=$${dollarCounter},`)
        queryValue.push(imageUrl)
        dollarCounter++
    }
    if (!!description) {
        queryText = queryText.concat(` description=$${dollarCounter},`)
        queryValue.push(description)
        dollarCounter++
    }
    queryText = queryText.slice(0, -1)
    if (!!whereId || !!whereTitle) queryText = queryText.concat(' WHERE')
    if (!!whereId) {
        queryText = queryText.concat(` id=$${dollarCounter},`)
        queryValue.push(whereId)
        dollarCounter++
    }
    if (!!whereTitle) {
        queryText = queryText.concat(` title ILIKE '%$${dollarCounter}%',`)
        queryValue.push(whereTitle)
        dollarCounter++
    }
    queryText = queryText.slice(0, -1)
    const query = {
        name: 'update',
        text: queryText,
        values: queryValue,
    }
    return db.query(query)
}

0 ответов

Другие вопросы по тегам