質問編集履歴
5
修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -19,9 +19,9 @@
|
|
19
19
|
もしこの方法をご存じの方がいらっしゃったらご教示いただけますと幸いです。
|
20
20
|
|
21
21
|
##### 考えていること2
|
22
|
-
上述したように IndexedDB への保存
|
22
|
+
上述したように IndexedDB への保存という案では実装できなそうだ、と悩んでいたのですが、そもそももしかして、zip ファイルを読んだ際にもキャッシュって効くのでしょうか?だとしたら IndexedDB への保存など不要?
|
23
23
|
|
24
|
-
実際に以下のコードを試したところ、1回目と2回目で半分くらいの時間になったので、どうやら zip ファイルにもキャッシュが効くのか?と思えたのですが、その確証が得れません。
|
24
|
+
実際に以下のような計測コードを試したところ、1回目と2回目で半分くらいの時間になったので、どうやら zip ファイルにもキャッシュが効くのか?と思えたのですが、その確証が得れません。
|
25
25
|
```JavaScript
|
26
26
|
(() => {
|
27
27
|
const DICT_PATH = "./dict";
|
@@ -64,7 +64,7 @@
|
|
64
64
|
|
65
65
|
ただこのライブラリが Kuromoji の辞書データである zip ファイルを解凍し、キャッシュし、よしなにしてくれるのか?までは調査、読解するスキルがありませんでした。
|
66
66
|
|
67
|
-
以上です。なんだかいまいちまとまっていない文章になってしまいましたが、質問としては Kuromoji の辞書データを効率的に(サーバー負荷を少なく)扱う方法
|
67
|
+
以上です。なんだかいまいちまとまっていない文章になってしまいましたが、質問としては Kuromoji の辞書データを効率的に(サーバー負荷を少なく)扱う方法か、またはそもそもそんな方法を模索しなくてもキャッシュされているから何もしなくてもいいのか、という2点になります。
|
68
68
|
|
69
69
|
よろしくお願い致します。
|
70
70
|
|
4
修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
### 前提
|
2
2
|
形態素解析を実装したいので、Kuromoji というライブラリを導入しました。
|
3
3
|
|
4
|
-
下記リンクのおかげもあり、基本的な動作は確認済みです。
|
5
|
-
|
6
|
-
> Kuromojiでかんたん形態素解析
|
7
|
-
|
4
|
+
[Kuromojiでかんたん形態素解析](https://zenn.dev/sdkfz181tiger/articles/daef6f0f8156d8) という記事のおかげもあり、基本的な動作は確認済みです。
|
8
5
|
|
9
6
|
### 目的
|
10
7
|
目的はこの辞書データの効率的な参照です。
|
@@ -76,7 +73,7 @@
|
|
76
73
|
・初回訪問した際は `initializeTokenizer()` を実行して IndexedDB に保存
|
77
74
|
・形態素解析の際は `analyzeText()` で解析
|
78
75
|
|
79
|
-
ということが出来るかも?と思ったのですが、初回訪問の `initializeTokenizer()` の時点で blob:https:/example.com/[UUID]/base.dat.gz などの GET ができないとコンソールにエラーが出まくってしまい、断念しました。(この方針も、そもそもブラウザが1回読んだ zip ファイルを自動でキャッシュしてくれるのであれば不要ですが。)
|
76
|
+
ということが出来るかも?と思ったのですが、初回訪問の `initializeTokenizer()` の時点で `blob:https:/example.com/[UUID]/base.dat.gz` など各種辞書データの GET ができないとコンソールにエラーが出まくってしまい、断念しました。(この方針も、そもそもブラウザが1回読んだ zip ファイルを自動でキャッシュしてくれるのであれば不要ですが。)
|
80
77
|
|
81
78
|
```JavaScript
|
82
79
|
/*----------------------------------------------------------------------------------------------------
|
3
タイトル
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
zipファイルをJavaScriptで読む際の効率的な方法(
|
1
|
+
zipファイルをJavaScriptで読む際の効率的な方法(1回目にローカルに保存し2回目以降はそれを読む方法、またはそんなことをせずとも勝手にキャッシュされ効率的になっているのか知りたい)
|
test
CHANGED
File without changes
|
2
タイトル
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
zipファイルをJavaScriptで読む際の効率的な方法
|
1
|
+
zipファイルをJavaScriptで読む際の効率的な方法(自分でどこかに保存し呼ぶ方法、またはそんなことをせずとも勝手にキャッシュされているのか)
|
test
CHANGED
File without changes
|
1
補足
test
CHANGED
File without changes
|
test
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
|
15
15
|
### 考えていること
|
16
16
|
##### 考えていること1
|
17
|
-
|
17
|
+
1回読んだ zip ファイルを何度も読むことは避けたいと思い、IndexedDB への保存を試みました。
|
18
18
|
しかし、Kuromoji は `kuromoji.builder()` なる関数によって辞書を参照するようで、その引数に指定できる値が辞書へのURLだけのようでした。
|
19
19
|
|
20
20
|
つまり、IndexedDB へ保存しても、それを `kuromoji.builder()` のために参照する方法がなさそう、ということです。
|
@@ -57,17 +57,138 @@
|
|
57
57
|
})();
|
58
58
|
```
|
59
59
|
|
60
|
-
どうなのでしょうか?もしキャッシュが効くのなら、特に何もしなくてもできる限り効率的な実装がなされていると考えていいのでしょうか
|
60
|
+
どうなのでしょうか?もしキャッシュが効くのなら、特に何もしなくてもできる限り効率的な実装がなされていると考えていいのでしょうか?
|
61
61
|
|
62
62
|
### 確認したこと
|
63
|
-
Kuromoji は CDN で下記リンクから読んで
|
63
|
+
Kuromoji は CDN で下記リンクから読んでおりまして、
|
64
64
|
https://cdn.jsdelivr.net/npm/kuromoji@0.1.2/build/kuromoji.js
|
65
65
|
|
66
|
-
これを
|
66
|
+
これを確認すると、辞書データの扱いに際しては [zlib.js というライブラリ](https://github.com/imaya/zlib.js/) を使っているようです。
|
67
67
|
|
68
|
-
ただこのライブラリが
|
68
|
+
ただこのライブラリが Kuromoji の辞書データである zip ファイルを解凍し、キャッシュし、よしなにしてくれるのか?までは調査、読解するスキルがありませんでした。
|
69
69
|
|
70
70
|
以上です。なんだかいまいちまとまっていない文章になってしまいましたが、質問としては Kuromoji の辞書データを効率的に(サーバー負荷を少なく)扱う方法と、そもそもそんな方法を模索しなくてもキャッシュされているのか否か、という2点になります。
|
71
71
|
|
72
72
|
よろしくお願い致します。
|
73
73
|
|
74
|
+
### 補足
|
75
|
+
下記 JavaScript のように
|
76
|
+
・初回訪問した際は `initializeTokenizer()` を実行して IndexedDB に保存
|
77
|
+
・形態素解析の際は `analyzeText()` で解析
|
78
|
+
|
79
|
+
ということが出来るかも?と思ったのですが、初回訪問の `initializeTokenizer()` の時点で blob:https:/example.com/[UUID]/base.dat.gz などの GET ができないとコンソールにエラーが出まくってしまい、断念しました。(この方針も、そもそもブラウザが1回読んだ zip ファイルを自動でキャッシュしてくれるのであれば不要ですが。)
|
80
|
+
|
81
|
+
```JavaScript
|
82
|
+
/*----------------------------------------------------------------------------------------------------
|
83
|
+
|
84
|
+
File: kuromoji-manager.js
|
85
|
+
Path: /assets/js/module/lib/kuromoji-manager.js
|
86
|
+
Description: Kurromoji の管理モジュール
|
87
|
+
|
88
|
+
----------------------------------------------------------------------------------------------------*/
|
89
|
+
|
90
|
+
let tokenizer;
|
91
|
+
const DB_NAME = "kuromojiCacheDB";
|
92
|
+
const STORE_NAME = "dictionaryStore";
|
93
|
+
const DICT_PATH = "./dict";
|
94
|
+
|
95
|
+
/*--------------------------------------------------
|
96
|
+
解析
|
97
|
+
--------------------------------------------------*/
|
98
|
+
|
99
|
+
// 形態素解析を実行
|
100
|
+
function analyzeText(string) {
|
101
|
+
|
102
|
+
if (!tokenizer) {
|
103
|
+
const contents = "Tokenizer is not ready yet. Please wait...";
|
104
|
+
console.log('analyzeText() contents', contents);
|
105
|
+
return;
|
106
|
+
}
|
107
|
+
|
108
|
+
const tokens = tokenizer.tokenize(string);
|
109
|
+
const contents = tokens.map(token =>
|
110
|
+
`表層形: ${token.surface_form}, 品詞: ${token.pos}, 基本形: ${token.base_form}`
|
111
|
+
).join("\n");
|
112
|
+
|
113
|
+
console.log('analyzeText() contents', contents);
|
114
|
+
}
|
115
|
+
|
116
|
+
/*--------------------------------------------------
|
117
|
+
初期化
|
118
|
+
--------------------------------------------------*/
|
119
|
+
|
120
|
+
// IndexedDBに辞書データを保存
|
121
|
+
async function saveDictionaryToDB(data) {
|
122
|
+
const db = await openIndexedDB();
|
123
|
+
const transaction = db.transaction(STORE_NAME, "readwrite");
|
124
|
+
const store = transaction.objectStore(STORE_NAME);
|
125
|
+
store.put(data, "kuromoji_dict");
|
126
|
+
console.log("辞書データをIndexedDBに保存しました。");
|
127
|
+
}
|
128
|
+
|
129
|
+
// IndexedDBから辞書データを取得
|
130
|
+
async function getDictionaryFromDB() {
|
131
|
+
const db = await openIndexedDB();
|
132
|
+
const transaction = db.transaction(STORE_NAME, "readonly");
|
133
|
+
const store = transaction.objectStore(STORE_NAME);
|
134
|
+
return store.get("kuromoji_dict");
|
135
|
+
}
|
136
|
+
|
137
|
+
// IndexedDBを開く(または作成)
|
138
|
+
function openIndexedDB() {
|
139
|
+
return new Promise((resolve, reject) => {
|
140
|
+
const request = indexedDB.open(DB_NAME, 1);
|
141
|
+
request.onupgradeneeded = event => {
|
142
|
+
const db = event.target.result;
|
143
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
144
|
+
db.createObjectStore(STORE_NAME);
|
145
|
+
}
|
146
|
+
};
|
147
|
+
request.onsuccess = () => resolve(request.result);
|
148
|
+
request.onerror = () => reject(request.error);
|
149
|
+
});
|
150
|
+
}
|
151
|
+
|
152
|
+
// トークナイザーを初期化
|
153
|
+
async function initializeTokenizer() {
|
154
|
+
console.log("辞書データをロード中...");
|
155
|
+
|
156
|
+
const cachedData = await getDictionaryFromDB();
|
157
|
+
if (cachedData) {
|
158
|
+
console.log("IndexedDBから辞書データを読み込み中...");
|
159
|
+
// 辞書データをBlob URLに変換
|
160
|
+
const dicBlobURL = URL.createObjectURL(new Blob([cachedData]));
|
161
|
+
|
162
|
+
console.log('initializeTokenizer() dicBlobURL: ', dicBlobURL);
|
163
|
+
|
164
|
+
tokenizer = await buildTokenizer(dicBlobURL); // build関数をPromise化して利用
|
165
|
+
} else {
|
166
|
+
console.log("CDNから辞書データを取得中...");
|
167
|
+
tokenizer = await buildTokenizer(DICT_PATH);
|
168
|
+
// 辞書データをIndexedDBに保存する処理(省略)
|
169
|
+
}
|
170
|
+
}
|
171
|
+
|
172
|
+
// Kuromojiのビルダー関数をPromiseでラップする
|
173
|
+
function buildTokenizer(dicPath) {
|
174
|
+
return new Promise((resolve, reject) => {
|
175
|
+
kuromoji.builder({ dicPath: dicPath }).build((err, tokenizer) => {
|
176
|
+
if (err) {
|
177
|
+
reject(err);
|
178
|
+
} else {
|
179
|
+
resolve(tokenizer);
|
180
|
+
}
|
181
|
+
});
|
182
|
+
});
|
183
|
+
}
|
184
|
+
|
185
|
+
/*--------------------------------------------------
|
186
|
+
export
|
187
|
+
--------------------------------------------------*/
|
188
|
+
|
189
|
+
export default {
|
190
|
+
analyzeText,
|
191
|
+
initializeTokenizer,
|
192
|
+
}
|
193
|
+
```
|
194
|
+
|