/** * 每天运行一次,生成站点地图 */ const fs = require('fs'); const datefns = require('date-fns'); const models = require('../../models'); const categories = require('../../config/category'); const tags = require('../../config/tag'); const date = datefns.format(Date.now(), 'yyyy-MM-dd'); const sitemapPath = __dirname + '/../../dist/sitemap.xml'; const sitemapTempPath = __dirname + '/../../dist/sitemap.xml.temp'; // 生成站点地图 async function generateSitemap() { let commonXml = [ '', // '', '', ' ', ' https://art.pcoloring.com/en', ` ${date}`, ' daily', ' 1.0', ' ', ' ', ' https://art.pcoloring.com/en/category', ` ${date}`, ' daily', ' 0.8', ' ', ' ', ' https://art.pcoloring.com/en/tag', ` ${date}`, ' daily', ' 0.8', ' ', ' ', ' https://art.pcoloring.com/en/albums', ` ${date}`, ' weekly', ' 0.8', ' ', ' ', ' https://art.pcoloring.com/en/special', ` ${date}`, ' daily', ' 0.8', ' ', ' ', ' https://art.pcoloring.com/en/artists', ` ${date}`, ' monthly', ' 0.8', ' ', ' ', ' https://art.pcoloring.com/en/info', ` ${date}`, ' ', ]; // categories let categoriesXml = []; categories.forEach(e => { categoriesXml = categoriesXml.concat([ ' ', ` https://art.pcoloring.com/en/category/${e.id}`, ` ${date}`, ' ', ] ); }); console.log(categoriesXml); // tags let tagsXml = []; tags.forEach(e => { tagsXml = tagsXml.concat([ ' ', ` https://art.pcoloring.com/en/tag/${e.tag}`, ` ${date}`, ' ', ]); }); console.log(tagsXml); // albums let albums = await models.ArtAlbum .find({ pid: 'art', enabled: true }) .sort({ order: 'asc' }) .select('_id') .lean() .exec(); let albumsXml = []; albums.forEach(e => { albumsXml = albumsXml.concat([ ' ', ` https://art.pcoloring.com/en/coloring-page-album/${e._id}`, ` ${date}`, ' ', ]) }); console.log(albumsXml); // designers let designers = await models.Art.aggregate([ // 首先,过滤出 status = 9000 的文档 { $match: { open: true, status: 9000 } }, // 首先,根据 user 字段进行分组,并计算每个 user 出现的次数 { $group: { _id: '$user', count: { $sum: 1 } } }, // 然后,按照 count 字段进行降序排列 { $sort: { count: -1 } }, // 接着,与 users 集合进行连接,以获取用户的详细信息 { $lookup: { from: 'users', // 要连接的集合名称 localField: '_id', // 本地字段(即上一步分组后的 _id 字段) foreignField: '_id', // 要连接的集合中的字段 as: 'userDetails' // 连接后结果存储在新字段 userDetails 中 } }, // 展开 userDetails 数组,以便将用户信息提升到顶层 { $unwind: '$userDetails' }, // 调整输出格式,只保留需要的字段 { $project: { _id: 1, user: '$_id', count: 1, username: '$userDetails.username', name: '$userDetails.name' } }, // 限制返回的记录数量 { $limit: 40 } ]); let designersXml = []; designers.forEach(e => { designersXml = designersXml.concat([ ' ', ` https://art.pcoloring.com/en/artist/${e._id}`, ` ${date}`, ' ', ]) }); console.log(designersXml); // details let detailsXml = []; const cursor = await models.Art .find({ open: true, status: 9000 }) .select('name title') .sort({ publishTime: -1 }).cursor(); // 使用cursor,避免一次查询太多记录内存受不了 // 遍历游标中的每个文档 for await (const doc of cursor) { let uriTitle = doc.name; if (doc.title) { try { let titleJson = JSON.parse(doc.title); if (titleJson.en) uriTitle = titleJson.en; // URL 里还是尽量用英文title } catch (e) { console.error(e.message); } } let utf8name = encodeURIComponent(uriTitle.replace(/[\s_]+/g, '-')).toLowerCase(); detailsXml = detailsXml.concat([ ' ', ` https://art.pcoloring.com/en/coloring-page/${utf8name}-${doc._id}`, ` ${date}`, ' ', ]); console.log(`process detail ${doc._id} url done`); } let endXml = ['']; let sitemapXml = [...commonXml, ...categoriesXml, ...tagsXml, ...albumsXml, ...designersXml, ...detailsXml, ...endXml]; let sitemapXmlStr = sitemapXml.join('\n'); fs.writeFileSync(sitemapTempPath, sitemapXmlStr); // 先写入临时文件 fs.renameSync(sitemapTempPath, sitemapPath); // 再重命名 console.log('生成sitemap成功'); } function run() { generateSitemap(); } module.exports = { run } if (require.main == module) { run(); }