Skip to content

Commit

Permalink
perf(post): cache tags getter
Browse files Browse the repository at this point in the history
  • Loading branch information
SukkaW committed Jan 12, 2023
1 parent 4f2dde4 commit 12f3fa1
Showing 1 changed file with 36 additions and 33 deletions.
69 changes: 36 additions & 33 deletions lib/models/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const moment = require('moment');
const { extname, join, sep } = require('path');
const Promise = require('bluebird');
const Moment = require('./types/moment');
const { full_url_for } = require('hexo-util');
const { full_url_for, Cache } = require('hexo-util');

function pickID(data) {
return data._id;
Expand All @@ -15,10 +15,12 @@ function removeEmptyTag(tags) {
return tags.filter(tag => tag != null && tag !== '').map(tag => `${tag}`);
}

const tagsGetterCache = new Cache();

module.exports = ctx => {
const Post = new Schema({
id: String,
title: {type: String, default: ''},
title: { type: String, default: '' },
date: {
type: Moment,
default: moment,
Expand All @@ -30,22 +32,22 @@ module.exports = ctx => {
language: ctx.config.languages,
timezone: ctx.config.timezone
},
comments: {type: Boolean, default: true},
layout: {type: String, default: 'post'},
_content: {type: String, default: ''},
source: {type: String, required: true},
slug: {type: String, required: true},
comments: { type: Boolean, default: true },
layout: { type: String, default: 'post' },
_content: { type: String, default: '' },
source: { type: String, required: true },
slug: { type: String, required: true },
photos: [String],
link: {type: String, default: ''},
raw: {type: String, default: ''},
published: {type: Boolean, default: true},
content: {type: String},
excerpt: {type: String},
more: {type: String}
link: { type: String, default: '' },
raw: { type: String, default: '' },
published: { type: Boolean, default: true },
content: { type: String },
excerpt: { type: String },
more: { type: String }
});

Post.virtual('path').get(function() {
const path = ctx.execFilterSync('post_permalink', this, {context: ctx});
const path = ctx.execFilterSync('post_permalink', this, { context: ctx });
return typeof path === 'string' ? path : '';
});

Expand All @@ -66,9 +68,9 @@ module.exports = ctx => {
const PostTag = ctx.model('PostTag');
const Tag = ctx.model('Tag');

const ids = PostTag.find({post_id: this._id}, {lean: true}).map(item => item.tag_id);
const ids = PostTag.find({ post_id: this._id }, { lean: true }).map(item => item.tag_id);

return Tag.find({_id: {$in: ids}});
return Tag.find({ _id: { $in: ids } });
});

Post.method('notPublished', function() {
Expand All @@ -82,29 +84,30 @@ module.exports = ctx => {
// If the post is unpublished then the tag needs to be removed, thus the function cannot be returned early here
tags = [];
}
tagsGetterCache.flush();
tags = removeEmptyTag(tags);

const PostTag = ctx.model('PostTag');
const Tag = ctx.model('Tag');
const id = this._id;
const existed = PostTag.find({post_id: id}, {lean: true}).map(pickID);
const existed = PostTag.find({ post_id: id }, { lean: true }).map(pickID);

return Promise.map(tags, tag => {
// Find the tag by name
const data = Tag.findOne({name: tag}, {lean: true});
const data = Tag.findOne({ name: tag }, { lean: true });
if (data) return data;

// Insert the tag if not exist
return Tag.insert({name: tag}).catch(err => {
return Tag.insert({ name: tag }).catch(err => {
// Try to find the tag again. Throw the error if not found
const data = Tag.findOne({name: tag}, {lean: true});
const data = Tag.findOne({ name: tag }, { lean: true });

if (data) return data;
throw err;
});
}).map(tag => {
// Find the reference
const ref = PostTag.findOne({post_id: id, tag_id: tag._id}, {lean: true});
const ref = PostTag.findOne({ post_id: id, tag_id: tag._id }, { lean: true });
if (ref) return ref;

// Insert the reference if not exist
Expand All @@ -123,9 +126,9 @@ module.exports = ctx => {
const PostCategory = ctx.model('PostCategory');
const Category = ctx.model('Category');

const ids = PostCategory.find({post_id: this._id}, {lean: true}).map(item => item.category_id);
const ids = PostCategory.find({ post_id: this._id }, { lean: true }).map(item => item.category_id);

return Category.find({_id: {$in: ids}});
return Category.find({ _id: { $in: ids } });
});

Post.method('setCategories', function(cats) {
Expand All @@ -143,7 +146,7 @@ module.exports = ctx => {
const Category = ctx.model('Category');
const id = this._id;
const allIds = [];
const existed = PostCategory.find({post_id: id}, {lean: true}).map(pickID);
const existed = PostCategory.find({ post_id: id }, { lean: true }).map(pickID);
const hasHierarchy = cats.filter(Array.isArray).length > 0;

// Add a hierarchy of categories
Expand All @@ -156,8 +159,8 @@ module.exports = ctx => {
// Find the category by name
const data = Category.findOne({
name: cat,
parent: i ? parentIds[i - 1] : {$exists: false}
}, {lean: true});
parent: i ? parentIds[i - 1] : { $exists: false }
}, { lean: true });

if (data) {
allIds.push(data._id);
Expand All @@ -166,15 +169,15 @@ module.exports = ctx => {
}

// Insert the category if not exist
const obj = {name: cat};
const obj = { name: cat };
if (i) obj.parent = parentIds[i - 1];

return Category.insert(obj).catch(err => {
// Try to find the category again. Throw the error if not found
const data = Category.findOne({
name: cat,
parent: i ? parentIds[i - 1] : {$exists: false}
}, {lean: true});
parent: i ? parentIds[i - 1] : { $exists: false }
}, { lean: true });

if (data) return data;
throw err;
Expand All @@ -189,7 +192,7 @@ module.exports = ctx => {
return (hasHierarchy ? Promise.each(cats, addHierarchy) : Promise.resolve(addHierarchy(cats))
).then(() => allIds).map(catId => {
// Find the reference
const ref = PostCategory.findOne({post_id: id, category_id: catId}, {lean: true});
const ref = PostCategory.findOne({ post_id: id, category_id: catId }, { lean: true });
if (ref) return ref;

// Insert the reference if not exist
Expand All @@ -204,19 +207,19 @@ module.exports = ctx => {
// Remove PostTag references
Post.pre('remove', data => {
const PostTag = ctx.model('PostTag');
return PostTag.remove({post_id: data._id});
return PostTag.remove({ post_id: data._id });
});

// Remove PostCategory references
Post.pre('remove', data => {
const PostCategory = ctx.model('PostCategory');
return PostCategory.remove({post_id: data._id});
return PostCategory.remove({ post_id: data._id });
});

// Remove assets
Post.pre('remove', data => {
const PostAsset = ctx.model('PostAsset');
return PostAsset.remove({post: data._id});
return PostAsset.remove({ post: data._id });
});

return Post;
Expand Down

0 comments on commit 12f3fa1

Please sign in to comment.