Develop a Node.js application that interacts with a PostgreSQL database to store and retrieve information about books (title, author, genre, publication date), and allows users to filter the results based on these attributes.
PLAINFORMAT
const express = require('express');
const { Pool } = require('pg');

// Set up the PostgreSQL database connection
const pool = new Pool({
    user: 'your_username',
    host: 'localhost',
    database: 'booksdb',
    password: 'your_password',
    port: 5432,
});

const app = express();
app.use(express.json());

// Create a new book
app.post('/books', async (req, res) => {
    const { title, author, genre, publication_date } = req.body;
    try {
        const result = await pool.query(
            'INSERT INTO books (title, author, genre, publication_date) VALUES ($1, $2, $3, $4)',
            [title, author, genre, publication_date]
        );
        res.status(201).send('Book added');
    } catch (err) {
        console.error(err);
        res.status(500).send('Server error');
    }
});

// Get all books
app.get('/books', async (req, res) => {
    try {
        const result = await pool.query('SELECT * FROM books');
        res.json(result.rows);
    } catch (err) {
        console.error(err);
        res.status(500).send('Server error');
    }
});

// Update a book by ID
app.put('/books/:id', async (req, res) => {
    const id = parseInt(req.params.id);
    const { title, author, genre, publication_date } = req.body;

    try {
        const result = await pool.query(
            'UPDATE books SET title=$1, author=$2, genre=$3, publication_date=$4 WHERE id=$5',
            [title, author, genre, publication_date, id]
        );
        res.send('Book updated');
    } catch (err) {
        console.error(err);
        res.status(500).send('Server error');
    }
});

// Delete a book by ID
app.delete('/books/:id', async (req, res) => {
    const id = parseInt(req.params.id);

    try {
        const result = await pool.query('DELETE FROM books WHERE id=$1', [id]);
        res.send('Book deleted');
    } catch (err) {
        console.error(err);
        res.status(500).send('Server error');
    }
});

// Get filtered books
app.get('/books/filter', async (req, res) => {
    const { title, author, genre, publication_date } = req.query;
    let query = 'SELECT * FROM books WHERE true';
    const queryParams = [];

    if (title) {
        query += ' AND title ILIKE $' + (queryParams.length + 1);
        queryParams.push('%' + title + '%');
    }

    if (author) {
        query += ' AND author ILIKE $' + (queryParams.length + 1);
        queryParams.push('%' + author + '%');
    }

    if (genre) {
        query += ' AND genre ILIKE $' + (queryParams.length + 1);
        queryParams.push('%' + genre + '%');
    }

    if (publication_date) {
        query += ' AND publication_date = $' + (queryParams.length + 1);
        queryParams.push(publication_date);
    }

    try {
        const result = await pool.query(query, queryParams);
        res.json(result.rows);
    } catch (err) {
        console.error(err);
        res.status(500).send('Server error');
    }
});

// Start the server
app.listen(3000, () => {
    console.log('Server is running on port 3000');
});