【发布时间】:2021-05-18 22:57:41
【问题描述】:
我有两个模型,一个视频模型和一个全局统计模型。视频模型存储标签的字符串数组。全局统计模型存储了一个包含tag 和count 的tagCountSchema 数组。
我正在编写一个函数,该函数使用视频文档中的数据删除和重建全局统计文档。这包括在全局统计文档中重建唯一标签列表及其计数。
const videoSchema = new mongoose.Schema({
tags: [{ type: String }],
});
const tagCountSchema = new mongoose.Schema({
tag: { type: String, required: true },
count: { type: Number, default: 1 },
}, { _id: false });
const statisticSchema = new mongoose.Schema({
is: { type: String, default: 'global' },
tags: [tagCountSchema],
});
const Statistic = mongoose.model('Statistic', statisticSchema );
const Video = mongoose.model('Video', videoSchema );
// Rebuild the statistics document
let statistics = await Statistic.findOne({ is: 'global' });
let videos = await Video.find({});
let map = statistics.tags.map(e => e.tag);
for (let video of videos) {
for (let tag of video.tags) {
const index = map.indexOf(tag);
if (index === -1) {
statistics.tags.push({ tag: tag, count: 1 });
map.push(tag);
} else {
statistics.tags[index].count++;
}
}
}
await statistics.save();
但是,在上面的函数中使用indexOf() 使得重建统计数据需要非常 很长时间。由于视频有很多唯一标签,全局统计文档中的唯一标签数组变得非常长,而且由于每个视频的每个标签都需要调用indexOf(),因此该函数需要很长时间才能完成。
我测试了这个函数的一个版本,它将标签作为对象存储在数据库中,并使用Object.keys 来更新统计文档中的标签。这速度快了一个数量级,但我已经意识到,如果将标签名称直接作为对象存储在数据库中会导致问题,如果标签名称非法用作数据库键。
从技术上讲,我也可以对标签对象进行字符串化以存储它,但这对于如何在我的代码的其他地方使用此函数并不传统。随着该函数循环播放视频,它还更新了其他文档(例如上传器)的类似统计信息,为了简单起见,我在代码中省略了这些统计信息。这意味着它需要对每个视频的对象进行字符串化和去字符串化。
我可以怎样提高这个功能的速度?
【问题讨论】:
-
你能展示一下
map之后的样子吗:let map = statistics.tags.map(e => e.name);? -
@codemonkey 抱歉,
name应该是tag,更新了问题。map是从tagCountSchema数组构建的标签名称数组,用于获取标签的索引。 -
我们所说的数组有多大?里面有多少元素?我要求探索在该循环之前对其进行预处理以使其查找速度更快的可能性。
-
唯一标签的数量目前接近 11,000 个,但它有增长的潜力。
标签: node.js arrays mongodb mongoose