SmolAgent_Tutorial/URL_Database_project/backend_server/app.js
2025-03-03 16:35:52 +08:00

304 lines
7.9 KiB
JavaScript

require('dotenv').config();
const express = require('express');
const { Pool } = require('pg');
// Install required packages
// npm install express pg
const app = express();
app.use(express.json());
// Configure PostgreSQL connection
const pool = new Pool({
user: process.env.PGUSER,
host: process.env.PGHOST,
database: process.env.PGDATABASE,
password: process.env.PGPASSWORD,
port: process.env.PGPORT,
});
// GET all records with pagination
app.get('/data', async (req, res) => {
console.log("Get all records with the table");
try {
const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10;
const offset = (page - 1) * limit;
const query = {
text: 'SELECT * FROM test_db_table ORDER BY id LIMIT $1 OFFSET $2',
values: [limit, offset],
};
const result = await pool.query(query);
res.json(result.rows);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// GET record by ID
app.get('/data/:id', async (req, res) => {
console.log("Get record by ID");
try {
const { id } = req.params;
const query = {
text: 'SELECT * FROM test_db_table WHERE id = $1',
values: [id],
};
const result = await pool.query(query);
if (result.rows.length === 0) {
return res.status(404).json({ message: 'Record not found' });
}
res.json(result.rows[0]);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// POST new record
app.post('/data', async (req, res) => {
console.log("Post new record");
try {
const { x, y, z } = req.body;
const query = {
text: 'INSERT INTO test_db_table(x, y, z) VALUES($1, $2, $3) RETURNING *',
values: [x, y, z],
};
const result = await pool.query(query);
res.status(201).json(result.rows[0]);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// PUT update record
app.put('/data/:id', async (req, res) => {
console.log("Update record by ID");
try {
const { id } = req.params;
const { x, y, z } = req.body;
const query = {
text: 'UPDATE test_db_table SET x = $1, y = $2, z = $3 WHERE id = $4 RETURNING *',
values: [x, y, z, id],
};
const result = await pool.query(query);
if (result.rows.length === 0) {
return res.status(404).json({ message: 'Record not found' });
}
res.json(result.rows[0]);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// DELETE record
app.delete('/data/:id', async (req, res) => {
console.log("Delete record by ID");
try {
const { id } = req.params;
const query = {
text: 'DELETE FROM test_db_table WHERE id = $1 RETURNING *',
values: [id],
};
const result = await pool.query(query);
if (result.rows.length === 0) {
return res.status(404).json({ message: 'Record not found' });
}
res.json({ message: 'Record deleted successfully' });
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// Advanced query endpoint with filtering and sorting
app.get('/data/search', async (req, res) => {
console.log("Advanced query endpoint with filtering and sorting");
try {
const {
min_x, max_x,
min_y, max_y,
min_z, max_z,
start_time, end_time,
sort_by, order = 'ASC'
} = req.query;
let conditions = [];
let values = [];
let valueIndex = 1;
if (min_x) {
conditions.push(`x >= $${valueIndex++}`);
values.push(min_x);
}
if (max_x) {
conditions.push(`x <= $${valueIndex++}`);
values.push(max_x);
}
// Similar for y and z ranges
if (start_time) {
conditions.push(`time >= $${valueIndex++}`);
values.push(start_time);
}
if (end_time) {
conditions.push(`time <= $${valueIndex++}`);
values.push(end_time);
}
const whereClause = conditions.length > 0
? 'WHERE ' + conditions.join(' AND ')
: '';
const orderClause = sort_by
? `ORDER BY ${sort_by} ${order}`
: 'ORDER BY id';
const query = {
text: `SELECT * FROM test_db_table ${whereClause} ${orderClause}`,
values: values,
};
const result = await pool.query(query);
res.json(result.rows);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// GET latest single record
app.get('/latest_data', async (req, res) => {
console.log("require the latest data on the database table");
try {
const query = {
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
};
const result = await pool.query(query);
if (result.rows.length === 0) {
return res.status(404).json({ message: 'No records found' });
}
res.json(result.rows[0]);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// This will handle both "/latest_data" and "/latest data"
app.get('/latest%20data', async (req, res) => {
console.log("require the latest data on the database table (20%))");
try {
const query = {
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
};
const result = await pool.query(query);
if (result.rows.length === 0) {
return res.status(404).json({ message: 'No records found' });
}
res.json(result.rows[0]);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// GET latest N records
app.get('/latest_data/:count', async (req, res) => {
try {
const count = parseInt(req.params.count) || 1;
// Add a reasonable limit to prevent excessive requests
const safeCount = Math.min(count, 100);
const query = {
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT $1',
values: [safeCount]
};
const result = await pool.query(query);
res.json(result.rows);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// GET latest data within a time window (e.g., last 5 minutes)
app.get('/latest_data/window', async (req, res) => {
try {
const minutes = parseInt(req.query.minutes) || 5;
// Add a reasonable limit to prevent excessive time windows
const safeMinutes = Math.min(minutes, 60);
const query = {
text: `
SELECT * FROM test_db_table
WHERE time >= NOW() - INTERVAL '${safeMinutes} minutes'
ORDER BY time DESC
`
};
const result = await pool.query(query);
res.json(result.rows);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
// GET latest data with real-time updates using Server-Sent Events (SSE)
app.get('/latest_data/stream', async (req, res) => {
// Set headers for SSE
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// Send initial data
try {
const query = {
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
};
const result = await pool.query(query);
if (result.rows.length > 0) {
res.write(`data: ${JSON.stringify(result.rows[0])}\n\n`);
}
} catch (err) {
console.error('Error fetching initial data:', err);
}
// Set up polling interval (e.g., every 5 seconds)
const intervalId = setInterval(async () => {
try {
const query = {
text: 'SELECT * FROM test_db_table ORDER BY time DESC LIMIT 1'
};
const result = await pool.query(query);
if (result.rows.length > 0) {
res.write(`data: ${JSON.stringify(result.rows[0])}\n\n`);
}
} catch (err) {
console.error('Error fetching update:', err);
}
}, 5000);
// Clean up on client disconnect
req.on('close', () => {
clearInterval(intervalId);
});
});
// Error handling middleware
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).json({ error: 'Something broke!' });
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});