summaryrefslogtreecommitdiff
path: root/src/tools/analysis/extract-user-keywords.ts
blob: 9f21ae2e17815f903521723f34e2acb2b0c2610f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
const MeCab = require('mecab-async');

import Post from '../../api/models/post';
import User from '../../api/models/user';
import config from '../../conf';

const mecab = new MeCab();
if (config.categorizer.mecab_command) mecab.command = config.categorizer.mecab_command;

function tokenize(text: string) {
	const tokens = this.mecab.parseSync(text)
		// キーワードのみ
		.filter(token => token[1] == '名詞' && (token[2] == '固有名詞' || token[2] == '一般'))
		// 取り出し
		.map(token => token[0]);

	return tokens;
}

// Fetch all users
User.find({}, {
	fields: {
		_id: true
	}
}).then(users => {
	let i = -1;

	const x = cb => {
		if (++i == users.length) return cb();
		extractKeywordsOne(users[i]._id, () => x(cb));
	};

	x(() => {
		console.log('complete');
	});
});

async function extractKeywordsOne(id, cb) {
	console.log(`extract keywords of ${id} ...`);

	// Fetch recent posts
	const recentPosts = await Post.find({
		user_id: id,
		text: {
			$exists: true
		}
	}, {
		sort: {
			_id: -1
		},
		limit: 1000,
		fields: {
			_id: false,
			text: true
		}
	});

	// 投稿が少なかったら中断
	if (recentPosts.length < 10) {
		return cb();
	}

	const keywords = {};

	// Extract keywords from recent posts
	recentPosts.forEach(post => {
		const keywordsOfPost = tokenize(post.text);

		keywordsOfPost.forEach(keyword => {
			if (keywords[keyword]) {
				keywords[keyword]++;
			} else {
				keywords[keyword] = 1;
			}
		});
	});

	// Sort keywords by frequency
	const keywordsSorted = Object.keys(keywords).sort((a, b) => keywords[b] - keywords[a]);

	// Lookup top 10 keywords
	const topKeywords = keywordsSorted.slice(0, 10);

	process.stdout.write(' >>> ' + topKeywords.join(' '));

	// Save
	User.update({ _id: id }, {
		$set: {
			keywords: topKeywords
		}
	}).then(() => {
		cb();
	});
}