පසුගිය Module එකේදී අපි අපේ Notes API එකේ දත්ත ගබඩා කිරීමට in-memory array එකක් භාවිතා කළා. මෙය ඉගෙනීමේ අරමුණු සඳහා හොඳ වුවත්, සැබෑ ලෝකයේදී (production) එය කිසිසේත්ම ප්රායෝගික නැහැ. ඊට හේතුව, server එක restart කළ සැණින් array එකේ ඇති සියලුම දත්ත මැකී යාමයි. Application එකක දත්ත ස්ථිරවම (persistently) ගබඩා කර තබා ගැනීමට අපට **database** එකක් අවශ්ය වේ.
Database එකක් මගින් දත්ත ක්රමවත් ලෙස ගබඩා කිරීමට, පහසුවෙන් නැවත ලබා ගැනීමට, සහ ආරක්ෂාකාරීව කළමනාකරණය කිරීමට ඉඩ සලසයි.
Databases ප්රධාන වශයෙන් වර්ග දෙකකට බෙදිය හැක:
මේවායේ දත්ත වගු (tables) වල පේළි (rows) සහ තීරු (columns) ලෙස ගබඩා කෙරේ. දත්ත අතර සබඳතා (relationships) පවත්වා ගැනීමට මේවා ඉතා සුදුසුය.
මේවායේ දත්ත විවිධ ආකෘති වලින් ගබඩා කළ හැක. බහුලවම භාවිතා වන්නේ JSON වැනි document ආකෘතියයි. වේගයෙන් වෙනස් වන, විශාල දත්ත ප්රමාණයක් සඳහා මේවා වඩාත් සුදුසුය.
SQLite යනු server එකක් අවශ්ය නොවන, file-based SQL database එකකි. කුඩා projects සහ ඉගෙනීම සඳහා මෙය ඉතාමත්ම සුදුසුය.
npm install sqlite3
`database.js` file එක:
const sqlite3 = require('sqlite3').verbose();
// 'notes.db' නමින් database file එකක් සාදා connection එකක් open කිරීම
const db = new sqlite3.Database('./notes.db', (err) => {
if (err) {
console.error(err.message);
}
console.log('Connected to the notes.db database.');
});
// 'notes' නමින් table එකක් නිර්මාණය කිරීම (දැනටමත් නොමැති නම්)
db.run(`CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT
)`, (err) => {
if (err) {
console.error(err.message);
}
console.log("'notes' table created or already exists.");
});
module.exports = db;
දැන් අපි අපේ Express app එකේ CRUD operations සඳහා මෙම database එක භාවිතා කරමු.
`index.js` file එක (SQLite සමඟ):
const express = require('express');
const app = express();
const port = 3000;
const db = require('./database.js'); // database connection එක import කිරීම
app.use(express.json());
// CREATE
app.post('/notes', (req, res) => {
const { title, content } = req.body;
const sql = `INSERT INTO notes (title, content) VALUES (?, ?)`;
db.run(sql, [title, content], function(err) {
if (err) {
return res.status(400).json({ "error": err.message });
}
res.status(201).json({ "id": this.lastID });
});
});
// READ (All)
app.get('/notes', (req, res) => {
const sql = "SELECT * FROM notes";
db.all(sql, [], (err, rows) => {
if (err) {
return res.status(400).json({ "error": err.message });
}
res.json({ "notes": rows });
});
});
// UPDATE
app.put('/notes/:id', (req, res) => {
const { title, content } = req.body;
const sql = `UPDATE notes SET title = ?, content = ? WHERE id = ?`;
db.run(sql, [title, content, req.params.id], function(err) {
if (err) {
return res.status(400).json({ "error": err.message });
}
res.json({ "message": "success", "changes": this.changes });
});
});
// DELETE
app.delete('/notes/:id', (req, res) => {
const sql = 'DELETE FROM notes WHERE id = ?';
db.run(sql, req.params.id, function(err) {
if (err) {
return res.status(400).json({ "error": err.message });
}
res.json({ "message": "deleted", "changes": this.changes });
});
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
මෙම code එක run කළ විට, `notes.db` නමින් file එකක් සෑදී, API endpoints හරහා කරන සියලුම වෙනස්කම් එම file එකේ ස්ථිරවම ගබඩා වේ.
ඔබට පෙනෙනවා ඇති SQL queries කෙලින්ම code එකේ ලිවීම තරමක් සංකීර්ණ සහ අපහසු විය හැකි බව. **ORM (Object-Relational Mapper)** සහ **ODM (Object-Document Mapper)** යනු මෙම ක්රියාවලිය පහසු කරන libraries වේ.
මේවා මගින් database tables හෝ collections, අපිට JavaScript වලදී හුරුපුරුදු objects සහ classes ලෙස හැසිරවීමට ඉඩ සලසයි. `db.run('SELECT * ...')` වැනි queries වෙනුවට `Note.find()` වැනි සරල functions භාවිතා කිරීමට අපට හැකිවේ.
Node.js ecosystem එකේ MongoDB සහ Mongoose සංයෝජනය ඉතාම ජනප්රියයි. අපි දැන් අපේ Notes API එක Mongoose භාවිතයෙන් නැවත ගොඩනගමු.
npm install mongoose
`index.js` file එක (Mongoose සමඟ):
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const port = 3000;
app.use(express.json());
// --- Database Connection ---
mongoose.connect('mongodb://localhost:27017/notesApp') // 'notesApp' is the database name
.then(() => console.log('MongoDB connected...'))
.catch(err => console.log(err));
// --- Mongoose Schema & Model ---
// Schema: දත්ත වල ව්යුහය (structure) නිර්වචනය කිරීම
const noteSchema = new mongoose.Schema({
title: { type: String, required: true },
content: String,
createdAt: { type: Date, default: Date.now }
});
// Model: Schema එක භාවිතා කර database collection එක සමඟ සන්නිවේදනය කරන interface එක
const Note = mongoose.model('Note', noteSchema);
// --- API Routes using Mongoose ---
// CREATE
app.post('/notes', async (req, res) => {
try {
const newNote = new Note({
title: req.body.title,
content: req.body.content
});
const savedNote = await newNote.save();
res.status(201).json(savedNote);
} catch (err) {
res.status(400).json({ message: err.message });
}
});
// READ (All)
app.get('/notes', async (req, res) => {
try {
const notes = await Note.find();
res.json(notes);
} catch (err) {
res.status(500).json({ message: err.message });
}
});
// UPDATE
app.put('/notes/:id', async (req, res) => {
try {
const updatedNote = await Note.findByIdAndUpdate(
req.params.id,
{ title: req.body.title, content: req.body.content },
{ new: true } // updated document එක return කිරීමට
);
res.json(updatedNote);
} catch (err) {
res.status(400).json({ message: err.message });
}
});
// DELETE
app.delete('/notes/:id', async (req, res) => {
try {
await Note.findByIdAndDelete(req.params.id);
res.json({ message: 'Note deleted successfully' });
} catch (err) {
res.status(500).json({ message: err.message });
}
});
app.listen(port, () => {
console.log(`Mongoose server running at http://localhost:${port}`);
});
Mongoose භාවිතයෙන් code එක කොතරම් පැහැදිලි සහ කියවීමට පහසු වී ඇත්දැයි බලන්න. SQL queries වෙනුවට `find()`, `save()`, `findByIdAndUpdate()` වැනි සරල, තේරුම්ගත හැකි methods භාවිතා කර ඇත.