74 lines
2.9 KiB
JavaScript
74 lines
2.9 KiB
JavaScript
// proxy/clean_devicestat_duplicates.js
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
// One-time cleanup script to deduplicate historical DeviceStat records.
|
|
// Keeps only the LATEST document per (agent_uuid, ip_address) pair,
|
|
// removing all older duplicates accumulated before the upsert fix.
|
|
//
|
|
// Usage: node proxy/clean_devicestat_duplicates.js
|
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
const path = require('path');
|
|
require('dotenv').config({ path: path.join(__dirname, '..', '.env.local') });
|
|
|
|
const mongoose = require('mongoose');
|
|
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/backone';
|
|
|
|
const DeviceStatSchema = new mongoose.Schema({
|
|
timestamp: { type: Date },
|
|
agent_uuid: { type: String },
|
|
site_uuid: { type: String },
|
|
ip_address: { type: String },
|
|
mac_address: { type: String },
|
|
device_label: String,
|
|
device_type: String,
|
|
os_label: String,
|
|
manufacturer: String,
|
|
download: Number,
|
|
upload: Number,
|
|
flows: Number,
|
|
last_seen: String,
|
|
}, { timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' } });
|
|
|
|
const DeviceStat = mongoose.model('DeviceStat', DeviceStatSchema);
|
|
|
|
async function run() {
|
|
console.log('[Cleanup] Connecting to MongoDB...');
|
|
await mongoose.connect(MONGODB_URI);
|
|
console.log('[Cleanup] Connected.');
|
|
|
|
// Find all unique (agent_uuid, ip_address) combinations
|
|
const groups = await DeviceStat.aggregate([
|
|
{ $group: {
|
|
_id: { agent_uuid: '$agent_uuid', ip_address: '$ip_address' },
|
|
ids: { $push: '$_id' },
|
|
timestamps: { $push: '$timestamp' },
|
|
count: { $sum: 1 },
|
|
}},
|
|
{ $match: { count: { $gt: 1 } } },
|
|
]);
|
|
|
|
console.log(`[Cleanup] Found ${groups.length} (agent_uuid, ip_address) pairs with duplicates.`);
|
|
let totalDeleted = 0;
|
|
|
|
for (const group of groups) {
|
|
// Sort the ids by matching timestamps - keep the latest
|
|
const paired = group.ids.map((id, i) => ({ id, ts: group.timestamps[i] }));
|
|
paired.sort((a, b) => new Date(b.ts) - new Date(a.ts));
|
|
|
|
// Keep the first (newest), delete the rest
|
|
const toDelete = paired.slice(1).map(p => p.id);
|
|
const result = await DeviceStat.deleteMany({ _id: { $in: toDelete } });
|
|
totalDeleted += result.deletedCount;
|
|
}
|
|
|
|
const remaining = await DeviceStat.countDocuments();
|
|
console.log(`[Cleanup] Done. Deleted ${totalDeleted} duplicate DeviceStat records.`);
|
|
console.log(`[Cleanup] Remaining DeviceStat documents: ${remaining}`);
|
|
await mongoose.disconnect();
|
|
}
|
|
|
|
run().catch(err => {
|
|
console.error('[Cleanup] Fatal error:', err.message);
|
|
process.exit(1);
|
|
});
|