mirror of
https://github.com/hotomoe/hotomoe
synced 2024-12-05 10:18:09 +09:00
Improve hashtag trend detection
This commit is contained in:
parent
91db24fcfc
commit
90337adbbc
@ -1,13 +1,23 @@
|
|||||||
import Note from '../../../../models/note';
|
import Note from '../../../../models/note';
|
||||||
|
|
||||||
|
/*
|
||||||
|
トレンドに載るためには「『直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上』のハッシュタグの上位5位以内に入る」ことが必要
|
||||||
|
ユニーク投稿数とはそのハッシュタグと投稿ユーザーのペアのカウントで、例えば同じユーザーが複数回同じハッシュタグを投稿してもそのハッシュタグのユニーク投稿数は1とカウントされる
|
||||||
|
*/
|
||||||
|
|
||||||
|
const rangeA = 1000 * 60 * 10; // 10分
|
||||||
|
const rangeB = 1000 * 60 * 60; // 1時間
|
||||||
|
const coefficient = 2; // 「n倍」の部分
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get trends of hashtags
|
* Get trends of hashtags
|
||||||
*/
|
*/
|
||||||
module.exports = () => new Promise(async (res, rej) => {
|
module.exports = () => new Promise(async (res, rej) => {
|
||||||
|
//#region 1. 直近Aの内に投稿されたハッシュタグ(とユーザーのペア)を集計
|
||||||
const data = await Note.aggregate([{
|
const data = await Note.aggregate([{
|
||||||
$match: {
|
$match: {
|
||||||
createdAt: {
|
createdAt: {
|
||||||
$gt: new Date(Date.now() - 1000 * 60 * 60)
|
$gt: new Date(Date.now() - rangeA)
|
||||||
},
|
},
|
||||||
tags: {
|
tags: {
|
||||||
$exists: true,
|
$exists: true,
|
||||||
@ -26,6 +36,7 @@ module.exports = () => new Promise(async (res, rej) => {
|
|||||||
userId: any;
|
userId: any;
|
||||||
}
|
}
|
||||||
}>;
|
}>;
|
||||||
|
//#endregion
|
||||||
|
|
||||||
if (data.length == 0) {
|
if (data.length == 0) {
|
||||||
return res([]);
|
return res([]);
|
||||||
@ -33,6 +44,7 @@ module.exports = () => new Promise(async (res, rej) => {
|
|||||||
|
|
||||||
const tags = [];
|
const tags = [];
|
||||||
|
|
||||||
|
// カウント
|
||||||
data.map(x => x._id).forEach(x => {
|
data.map(x => x._id).forEach(x => {
|
||||||
const i = tags.findIndex(tag => tag.name == x.tags);
|
const i = tags.findIndex(tag => tag.name == x.tags);
|
||||||
if (i != -1) {
|
if (i != -1) {
|
||||||
@ -45,11 +57,31 @@ module.exports = () => new Promise(async (res, rej) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const hots = tags
|
//#region 2. 1で取得したそれぞれのタグについて、「直近a分間のユニーク投稿数が今からa分前~今からb分前の間のユニーク投稿数のn倍以上」かどうかを判定する
|
||||||
|
const hotsPromises = tags.map(async tag => {
|
||||||
|
const passedCount = (await Note.distinct('userId', {
|
||||||
|
tags: tag,
|
||||||
|
createdAt: {
|
||||||
|
$lt: new Date(Date.now() - rangeA),
|
||||||
|
$gt: new Date(Date.now() - rangeB)
|
||||||
|
}
|
||||||
|
}) as any).length;
|
||||||
|
|
||||||
|
if (passedCount > (tag.count * coefficient)) {
|
||||||
|
return tag;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
const hots = (await Promise.all(hotsPromises))
|
||||||
|
.filter(x => x != null)
|
||||||
.sort((a, b) => b.count - a.count)
|
.sort((a, b) => b.count - a.count)
|
||||||
.map(tag => tag.name)
|
.map(tag => tag.name)
|
||||||
.slice(0, 5);
|
.slice(0, 5);
|
||||||
|
|
||||||
|
//#region 2で話題と判定されたタグそれぞれについて過去の投稿数グラフを取得する
|
||||||
const countPromises: Array<Promise<any[]>> = [];
|
const countPromises: Array<Promise<any[]>> = [];
|
||||||
|
|
||||||
const range = 20;
|
const range = 20;
|
||||||
@ -75,6 +107,7 @@ module.exports = () => new Promise(async (res, rej) => {
|
|||||||
$gt: new Date(Date.now() - (interval * range))
|
$gt: new Date(Date.now() - (interval * range))
|
||||||
}
|
}
|
||||||
})));
|
})));
|
||||||
|
//#endregion
|
||||||
|
|
||||||
const stats = hots.map((tag, i) => ({
|
const stats = hots.map((tag, i) => ({
|
||||||
tag,
|
tag,
|
||||||
|
Loading…
Reference in New Issue
Block a user