|
| 1 | +#!/usr/bin/env node |
| 2 | +/** |
| 3 | + * 向 Analyze 表插入 500 条测试数据 |
| 4 | + * 运行: node scripts/seed-analyze-data.mjs |
| 5 | + */ |
| 6 | + |
| 7 | +import { MongoClient } from 'mongodb' |
| 8 | + |
| 9 | +const MONGO_URI = process.env.MONGO_CONNECTION || 'mongodb://localhost:27017/mx-space' |
| 10 | +const COLLECTION_NAME = 'analyzes' |
| 11 | + |
| 12 | +// 模拟数据 |
| 13 | +const browsers = [ |
| 14 | + { name: 'Chrome', version: '120.0.0' }, |
| 15 | + { name: 'Firefox', version: '121.0' }, |
| 16 | + { name: 'Safari', version: '17.0' }, |
| 17 | + { name: 'Edge', version: '120.0.0' }, |
| 18 | + { name: 'Opera', version: '105.0' }, |
| 19 | +] |
| 20 | + |
| 21 | +const osList = [ |
| 22 | + { name: 'Windows', version: '10' }, |
| 23 | + { name: 'Windows', version: '11' }, |
| 24 | + { name: 'macOS', version: '14.0' }, |
| 25 | + { name: 'Linux', version: '' }, |
| 26 | + { name: 'iOS', version: '17.0' }, |
| 27 | + { name: 'Android', version: '14' }, |
| 28 | +] |
| 29 | + |
| 30 | +const devices = [ |
| 31 | + { type: 'desktop', vendor: '', model: '' }, |
| 32 | + { type: 'desktop', vendor: '', model: '' }, |
| 33 | + { type: 'desktop', vendor: '', model: '' }, |
| 34 | + { type: 'mobile', vendor: 'Apple', model: 'iPhone' }, |
| 35 | + { type: 'mobile', vendor: 'Samsung', model: 'Galaxy' }, |
| 36 | + { type: 'tablet', vendor: 'Apple', model: 'iPad' }, |
| 37 | +] |
| 38 | + |
| 39 | +const paths = [ |
| 40 | + '/posts/hello-world', |
| 41 | + '/posts/typescript-tips', |
| 42 | + '/posts/vue-best-practices', |
| 43 | + '/notes/1', |
| 44 | + '/notes/2', |
| 45 | + '/notes/3', |
| 46 | + '/pages/about', |
| 47 | + '/pages/links', |
| 48 | + '/', |
| 49 | + '/feed', |
| 50 | + '/sitemap.xml', |
| 51 | +] |
| 52 | + |
| 53 | +const referers = [ |
| 54 | + '', // 直接访问 |
| 55 | + '', |
| 56 | + '', |
| 57 | + 'https://www.google.com/search?q=blog', |
| 58 | + 'https://www.google.com/search?q=vue', |
| 59 | + 'https://www.baidu.com/s?wd=blog', |
| 60 | + 'https://www.bing.com/search?q=typescript', |
| 61 | + 'https://twitter.com/someuser/status/123', |
| 62 | + 'https://x.com/someuser/status/456', |
| 63 | + 'https://weibo.com/detail/123456', |
| 64 | + 'https://www.zhihu.com/question/123456', |
| 65 | + 'https://github.com/user/repo', |
| 66 | + 'https://reddit.com/r/programming', |
| 67 | + 'https://t.me/channel/123', |
| 68 | +] |
| 69 | + |
| 70 | +const countries = ['CN', 'US', 'JP', 'KR', 'GB', 'DE', 'FR', 'SG', 'HK', 'TW', null] |
| 71 | + |
| 72 | +function randomItem(arr) { |
| 73 | + return arr[Math.floor(Math.random() * arr.length)] |
| 74 | +} |
| 75 | + |
| 76 | +function randomIP() { |
| 77 | + return `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}` |
| 78 | +} |
| 79 | + |
| 80 | +function generateRecord(timestamp) { |
| 81 | + const browser = randomItem(browsers) |
| 82 | + const os = randomItem(osList) |
| 83 | + const device = randomItem(devices) |
| 84 | + |
| 85 | + return { |
| 86 | + ip: randomIP(), |
| 87 | + ua: { |
| 88 | + browser: { name: browser.name, version: browser.version, major: browser.version.split('.')[0] }, |
| 89 | + os: { name: os.name, version: os.version }, |
| 90 | + device: { type: device.type, vendor: device.vendor, model: device.model }, |
| 91 | + engine: { name: 'Blink', version: '120.0.0' }, |
| 92 | + cpu: { architecture: 'amd64' }, |
| 93 | + }, |
| 94 | + path: randomItem(paths), |
| 95 | + referer: randomItem(referers), |
| 96 | + country: randomItem(countries), |
| 97 | + timestamp: new Date(timestamp), |
| 98 | + } |
| 99 | +} |
| 100 | + |
| 101 | +async function main() { |
| 102 | + console.log('Connecting to MongoDB...') |
| 103 | + const client = new MongoClient(MONGO_URI) |
| 104 | + |
| 105 | + try { |
| 106 | + await client.connect() |
| 107 | + console.log('Connected!') |
| 108 | + |
| 109 | + const db = client.db() |
| 110 | + const collection = db.collection(COLLECTION_NAME) |
| 111 | + |
| 112 | + // 生成过去 7 天的数据 |
| 113 | + const now = Date.now() |
| 114 | + const sevenDaysAgo = now - 7 * 24 * 60 * 60 * 1000 |
| 115 | + |
| 116 | + const records = [] |
| 117 | + for (let i = 0; i < 500; i++) { |
| 118 | + const timestamp = sevenDaysAgo + Math.random() * (now - sevenDaysAgo) |
| 119 | + records.push(generateRecord(timestamp)) |
| 120 | + } |
| 121 | + |
| 122 | + console.log(`Inserting ${records.length} records...`) |
| 123 | + const result = await collection.insertMany(records) |
| 124 | + console.log(`Inserted ${result.insertedCount} records successfully!`) |
| 125 | + |
| 126 | + // 显示统计信息 |
| 127 | + const stats = await collection.aggregate([ |
| 128 | + { |
| 129 | + $facet: { |
| 130 | + total: [{ $count: 'count' }], |
| 131 | + byDevice: [ |
| 132 | + { $group: { _id: '$ua.device.type', count: { $sum: 1 } } }, |
| 133 | + { $sort: { count: -1 } }, |
| 134 | + ], |
| 135 | + byBrowser: [ |
| 136 | + { $group: { _id: '$ua.browser.name', count: { $sum: 1 } } }, |
| 137 | + { $sort: { count: -1 } }, |
| 138 | + ], |
| 139 | + }, |
| 140 | + }, |
| 141 | + ]).toArray() |
| 142 | + |
| 143 | + console.log('\n--- Statistics ---') |
| 144 | + console.log('Total records:', stats[0].total[0]?.count || 0) |
| 145 | + console.log('By device:', stats[0].byDevice) |
| 146 | + console.log('By browser:', stats[0].byBrowser) |
| 147 | + |
| 148 | + } catch (err) { |
| 149 | + console.error('Error:', err) |
| 150 | + process.exit(1) |
| 151 | + } finally { |
| 152 | + await client.close() |
| 153 | + console.log('\nDone!') |
| 154 | + } |
| 155 | +} |
| 156 | + |
| 157 | +main() |
0 commit comments