feat: add MongoDB systemd service and database initialization
- Create mongodb-tractatus.service for systemd management - Add installation script for service setup - Create init-db.js with complete collection schemas and indexes - Configure 10 MongoDB collections: documents, blog_posts, media_inquiries, case_submissions, resources, moderation_queue, users, citations, translations, koha_donations - Add indexes for performance optimization - Include verification and statistics output MongoDB Port: 27017 Database: tractatus_dev Status: Ready for service installation
This commit is contained in:
parent
4445b0e8d0
commit
4f8de209f3
3 changed files with 292 additions and 0 deletions
202
scripts/init-db.js
Normal file
202
scripts/init-db.js
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
#!/usr/bin/env node
|
||||
/**
|
||||
* Database Initialization Script for Tractatus
|
||||
*
|
||||
* Creates all required collections and indexes for the Tractatus platform
|
||||
* Run with: node scripts/init-db.js
|
||||
*/
|
||||
|
||||
const { MongoClient } = require('mongodb');
|
||||
const path = require('path');
|
||||
|
||||
// Load environment variables
|
||||
require('dotenv').config({ path: path.join(__dirname, '../.env') });
|
||||
|
||||
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/tractatus_dev';
|
||||
const DB_NAME = process.env.MONGODB_DB || 'tractatus_dev';
|
||||
|
||||
/**
|
||||
* Collection schemas and indexes
|
||||
*/
|
||||
const COLLECTIONS = {
|
||||
documents: {
|
||||
indexes: [
|
||||
{ keys: { slug: 1 }, options: { unique: true } },
|
||||
{ keys: { quadrant: 1 } },
|
||||
{ keys: { 'metadata.document_code': 1 } },
|
||||
{ keys: { search_index: 'text' } },
|
||||
{ keys: { 'metadata.date_created': -1 } }
|
||||
]
|
||||
},
|
||||
|
||||
blog_posts: {
|
||||
indexes: [
|
||||
{ keys: { slug: 1 }, options: { unique: true } },
|
||||
{ keys: { status: 1 } },
|
||||
{ keys: { published_at: -1 } },
|
||||
{ keys: { 'author.type': 1 } },
|
||||
{ keys: { tags: 1 } }
|
||||
]
|
||||
},
|
||||
|
||||
media_inquiries: {
|
||||
indexes: [
|
||||
{ keys: { 'contact.email': 1 } },
|
||||
{ keys: { status: 1 } },
|
||||
{ keys: { created_at: -1 } },
|
||||
{ keys: { 'ai_triage.urgency': 1 } }
|
||||
]
|
||||
},
|
||||
|
||||
case_submissions: {
|
||||
indexes: [
|
||||
{ keys: { 'submitter.email': 1 } },
|
||||
{ keys: { 'moderation.status': 1 } },
|
||||
{ keys: { submitted_at: -1 } },
|
||||
{ keys: { 'ai_review.relevance_score': -1 } }
|
||||
]
|
||||
},
|
||||
|
||||
resources: {
|
||||
indexes: [
|
||||
{ keys: { url: 1 }, options: { unique: true } },
|
||||
{ keys: { category: 1 } },
|
||||
{ keys: { status: 1 } },
|
||||
{ keys: { alignment_score: -1 } }
|
||||
]
|
||||
},
|
||||
|
||||
moderation_queue: {
|
||||
indexes: [
|
||||
{ keys: { item_type: 1 } },
|
||||
{ keys: { status: 1 } },
|
||||
{ keys: { priority: 1 } },
|
||||
{ keys: { created_at: -1 } },
|
||||
{ keys: { quadrant: 1 } }
|
||||
]
|
||||
},
|
||||
|
||||
users: {
|
||||
indexes: [
|
||||
{ keys: { email: 1 }, options: { unique: true } },
|
||||
{ keys: { role: 1 } },
|
||||
{ keys: { created_at: -1 } }
|
||||
]
|
||||
},
|
||||
|
||||
citations: {
|
||||
indexes: [
|
||||
{ keys: { document_id: 1 } },
|
||||
{ keys: { citation_type: 1 } },
|
||||
{ keys: { cited_at: -1 } }
|
||||
]
|
||||
},
|
||||
|
||||
translations: {
|
||||
indexes: [
|
||||
{ keys: { original_id: 1, language: 1 }, options: { unique: true } },
|
||||
{ keys: { language: 1 } },
|
||||
{ keys: { status: 1 } }
|
||||
]
|
||||
},
|
||||
|
||||
koha_donations: {
|
||||
indexes: [
|
||||
{ keys: { stripe_payment_id: 1 }, options: { unique: true } },
|
||||
{ keys: { 'donor.email': 1 } },
|
||||
{ keys: { frequency: 1 } },
|
||||
{ keys: { timestamp: -1 } },
|
||||
{ keys: { status: 1 } }
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize database
|
||||
*/
|
||||
async function initializeDatabase() {
|
||||
console.log('🚀 Starting Tractatus database initialization...\n');
|
||||
console.log(`MongoDB URI: ${MONGODB_URI}`);
|
||||
console.log(`Database: ${DB_NAME}\n`);
|
||||
|
||||
const client = new MongoClient(MONGODB_URI);
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
console.log('✅ Connected to MongoDB\n');
|
||||
|
||||
const db = client.db(DB_NAME);
|
||||
|
||||
// Get existing collections
|
||||
const existingCollections = await db.listCollections().toArray();
|
||||
const existingNames = existingCollections.map(c => c.name);
|
||||
|
||||
// Create collections and indexes
|
||||
for (const [collectionName, config] of Object.entries(COLLECTIONS)) {
|
||||
console.log(`📦 Processing collection: ${collectionName}`);
|
||||
|
||||
// Create collection if it doesn't exist
|
||||
if (!existingNames.includes(collectionName)) {
|
||||
await db.createCollection(collectionName);
|
||||
console.log(` ✓ Created collection`);
|
||||
} else {
|
||||
console.log(` ⊙ Collection already exists`);
|
||||
}
|
||||
|
||||
// Create indexes
|
||||
const collection = db.collection(collectionName);
|
||||
for (const indexSpec of config.indexes) {
|
||||
try {
|
||||
const indexName = await collection.createIndex(
|
||||
indexSpec.keys,
|
||||
indexSpec.options || {}
|
||||
);
|
||||
console.log(` ✓ Created index: ${indexName}`);
|
||||
} catch (error) {
|
||||
if (error.code === 85 || error.code === 86) {
|
||||
// Index already exists
|
||||
console.log(` ⊙ Index already exists`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log('');
|
||||
}
|
||||
|
||||
// Verify collections
|
||||
console.log('🔍 Verifying database setup...');
|
||||
const finalCollections = await db.listCollections().toArray();
|
||||
console.log(` ✓ Total collections: ${finalCollections.length}`);
|
||||
|
||||
// Display collection statistics
|
||||
console.log('\n📊 Collection Statistics:');
|
||||
for (const collectionName of Object.keys(COLLECTIONS)) {
|
||||
const collection = db.collection(collectionName);
|
||||
const count = await collection.countDocuments();
|
||||
const indexes = await collection.indexes();
|
||||
console.log(` ${collectionName}:`);
|
||||
console.log(` Documents: ${count}`);
|
||||
console.log(` Indexes: ${indexes.length}`);
|
||||
}
|
||||
|
||||
console.log('\n✨ Database initialization complete!\n');
|
||||
console.log('Next steps:');
|
||||
console.log(' 1. Run document migration: npm run migrate:docs');
|
||||
console.log(' 2. Create admin user: npm run seed:admin');
|
||||
console.log(' 3. Start development server: npm run dev\n');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Error initializing database:', error);
|
||||
process.exit(1);
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Run initialization
|
||||
if (require.main === module) {
|
||||
initializeDatabase().catch(console.error);
|
||||
}
|
||||
|
||||
module.exports = { initializeDatabase, COLLECTIONS };
|
||||
53
scripts/install-mongodb-service.sh
Executable file
53
scripts/install-mongodb-service.sh
Executable file
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Install mongodb-tractatus systemd service
|
||||
# Run with: sudo ./install-mongodb-service.sh
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
SERVICE_NAME="mongodb-tractatus.service"
|
||||
SERVICE_FILE="./mongodb-tractatus.service"
|
||||
SYSTEMD_DIR="/etc/systemd/system"
|
||||
|
||||
echo "Installing MongoDB Tractatus systemd service..."
|
||||
|
||||
# Check if running as root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Error: This script must be run with sudo"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if service file exists
|
||||
if [ ! -f "$SERVICE_FILE" ]; then
|
||||
echo "Error: $SERVICE_FILE not found in current directory"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy service file to systemd directory
|
||||
echo "Copying service file to $SYSTEMD_DIR..."
|
||||
cp "$SERVICE_FILE" "$SYSTEMD_DIR/$SERVICE_NAME"
|
||||
|
||||
# Set correct permissions
|
||||
chmod 644 "$SYSTEMD_DIR/$SERVICE_NAME"
|
||||
|
||||
# Reload systemd daemon
|
||||
echo "Reloading systemd daemon..."
|
||||
systemctl daemon-reload
|
||||
|
||||
# Enable service to start on boot
|
||||
echo "Enabling service to start on boot..."
|
||||
systemctl enable "$SERVICE_NAME"
|
||||
|
||||
echo ""
|
||||
echo "MongoDB Tractatus service installed successfully!"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " Start: sudo systemctl start $SERVICE_NAME"
|
||||
echo " Stop: sudo systemctl stop $SERVICE_NAME"
|
||||
echo " Restart: sudo systemctl restart $SERVICE_NAME"
|
||||
echo " Status: sudo systemctl status $SERVICE_NAME"
|
||||
echo " Logs: sudo journalctl -u $SERVICE_NAME -f"
|
||||
echo ""
|
||||
echo "To start the service now, run:"
|
||||
echo " sudo systemctl start $SERVICE_NAME"
|
||||
37
scripts/mongodb-tractatus.service
Normal file
37
scripts/mongodb-tractatus.service
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
[Unit]
|
||||
Description=MongoDB Database Server for Tractatus
|
||||
Documentation=https://docs.mongodb.org/manual
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
User=theflow
|
||||
Group=theflow
|
||||
|
||||
# MongoDB executable and configuration
|
||||
ExecStart=/home/theflow/projects/mongodb/mongodb-server/bin/mongod \
|
||||
--port 27017 \
|
||||
--dbpath /home/theflow/projects/tractatus/data/mongodb \
|
||||
--logpath /home/theflow/projects/tractatus/logs/mongodb.log \
|
||||
--fork \
|
||||
--quiet
|
||||
|
||||
ExecStop=/home/theflow/projects/mongodb/mongodb-server/bin/mongod \
|
||||
--port 27017 \
|
||||
--dbpath /home/theflow/projects/tractatus/data/mongodb \
|
||||
--shutdown
|
||||
|
||||
# Restart policy
|
||||
Restart=on-failure
|
||||
RestartSec=5
|
||||
|
||||
# Security settings
|
||||
PrivateTmp=true
|
||||
NoNewPrivileges=true
|
||||
LimitNOFILE=64000
|
||||
|
||||
# Working directory
|
||||
WorkingDirectory=/home/theflow/projects/tractatus
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Loading…
Add table
Reference in a new issue