FileMaker + kuromoji.js で形態素解析の序章

# はじめに
## 前書き
* 本記事は [FileMaker Advent Calendar 2021](https://qiita.com/advent-calendar/2021/filemaker) 17 日目の記事です。

## 対象読者
* Claris FileMaker Pro 19 ユーザ
* FileMaker の WEB ビューアを用いて形態素解析をやってみたいという（奇特な）方

## 検証環境
* Windows 10 Pro
* FileMaker Pro 19.4.1
* kuromoji.js 0.1.2
* インターネット接続環境

## kuromoji.js とは
* kuromoji をベースとした JavaScript による形態素解析のためのライブラリ
* https://github.com/takuyaa/kuromoji.js/

## 形態素解析とは
* [Wikipedia - 形態素解析](https://ja.wikipedia.org/wiki/%E5%BD%A2%E6%85%8B%E7%B4%A0%E8%A7%A3%E6%9E%90)
* 以下のような感じのもの

|文字列|読み|原形|品詞の種類|活用の種類|活用形|
|:----|:----|:----|:----|:----|:----|
|お待ち|オマチ|お待ち|名詞-サ変接続||
|し|シ|する|動詞-自立|サ変・スル|連用形|
|て|テ|て|助詞-接続助詞||
|おり|オリ|おる|動詞-非自立|五段・ラ行|連用形|
|ます|マス|ます|助動詞|特殊・マス|基本形|
|。|。|。|記号-句点| | |

# 準備
## kuromoji.js
### JSDelivr
* 今回、WEB ビューアにおけるローカルリソース問題を避けるために、オンライン環境のリソースを使用します
* 具体的には CDN として有名な [JSDELVIR](https://www.jsdelivr.com/) さんを直接参照させていただきます
  * https://www.jsdelivr.com/package/npm/kuromoji

## FileMaker
### fmp12 ファイル作成
* ファイル名は何でも構いませんが今回は `kuromoji.fmp12` として作成

### テーブル構成
* 以下のように、`texts` を作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/6885dc76-e06e-8b37-427d-edd9ffe1d0a3.png)

### texts テーブル
* 以下のように。`input` と `g_for_webview` があればよい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/6992093b-5fdf-5144-0353-cf09bb06d766.png)



### グローバル変数設定
* `$$kuromoji_js_path` `$$kuromoji_dict_path` という二つのグローバル変数を設定する
* 値はそれぞれ以下の通り

```
"https://cdn.jsdelivr.net/npm/kuromoji@0.1.2/build/kuromoji.js"
"https://cdn.jsdelivr.net/npm/kuromoji@0.1.2/dict/"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/8341960e-c421-01c3-0330-7487f19ec60d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/021a1745-3938-446e-1429-f443592dee02.png)

* これらを `open` スクリプトで実行させる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/cf9ba4f1-5e6b-10f4-5878-77d96ec49ae5.png)

### レイアウト
* 適当に配置。WEB ビューアの設定は後でやるので、今は置いておくだけでヨシ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/edaa8549-a1c2-30d4-f656-96446f2fde01.png)

* `OnLayoutEnter` をトリガとして `open` スクリプトを設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/a5fc8f7b-d4ac-53a9-e03f-88932091af88.png)

* ここまでで下準備は完了です

# 作成
## g_for_webview フィールドの設定
* 以下のように記述
* `[[[kuromoji_js_path]]]` などは、後で WEB ビューアの定義側で Substitute 関数をかけて置換する。ここでは可読性を上げるため、通常有り得ない文字列として置いておく

```html
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="result"></div>

<script src="[[[kuromoji_js_path]]]"></script>
<script>
kuromoji.builder({ dicPath: "[[[kuromoji_dict_path]]]" }).build(function (err, tokenizer) {
    var result = tokenizer.tokenize("[[[input]]]")
    var result = JSON.stringify(result, null, 2)
    document.getElementById('result').innerHTML = result
})
</script>
</body>
</html>
```

## WEB ビューアの設定
* 以下のように記述

```sh
Let (
  [
    kuromoji_js_path = $$kuromoji_js_path;
    kuromoji_dict_path = $$kuromoji_dict_path;
    input = texts::input;

    result = texts::g_for_webview;
    result = Substitute ( result ; "[[[kuromoji_js_path]]]" ; kuromoji_js_path );
    result = Substitute ( result ; "[[[kuromoji_dict_path]]]" ; kuromoji_dict_path );
    result = Substitute ( result ; "[[[input]]]" ; input )
  ];

  result
)
```

## 出力結果の確認
### こんな感じ
* `すもももももももものうち` の場合

```json
[ { "word_id": 415760, "word_type": "KNOWN", "word_position": 1, "surface_form": "すもも", "pos": "名詞", "pos_detail_1": "一般", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "すもも", "reading": "スモモ", "pronunciation": "スモモ" }, { "word_id": 93220, "word_type": "KNOWN", "word_position": 4, "surface_form": "も", "pos": "助詞", "pos_detail_1": "係助詞", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "も", "reading": "モ", "pronunciation": "モ" }, { "word_id": 1614710, "word_type": "KNOWN", "word_position": 5, "surface_form": "もも", "pos": "名詞", "pos_detail_1": "一般", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "もも", "reading": "モモ", "pronunciation": "モモ" }, { "word_id": 93220, "word_type": "KNOWN", "word_position": 7, "surface_form": "も", "pos": "助詞", "pos_detail_1": "係助詞", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "も", "reading": "モ", "pronunciation": "モ" }, { "word_id": 1614710, "word_type": "KNOWN", "word_position": 8, "surface_form": "もも", "pos": "名詞", "pos_detail_1": "一般", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "もも", "reading": "モモ", "pronunciation": "モモ" }, { "word_id": 93100, "word_type": "KNOWN", "word_position": 10, "surface_form": "の", "pos": "助詞", "pos_detail_1": "連体化", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "の", "reading": "ノ", "pronunciation": "ノ" }, { "word_id": 62510, "word_type": "KNOWN", "word_position": 11, "surface_form": "うち", "pos": "名詞", "pos_detail_1": "非自立", "pos_detail_2": "副詞可能", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "うち", "reading": "ウチ", "pronunciation": "ウチ" } ]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/947e3ea0-171d-7e5f-d321-8ae3c7437e48.png)

* `世界をリードするワークプレイス・イノベーション・プラットフォーム。` の場合

```json
[ { "word_id": 2633350, "word_type": "KNOWN", "word_position": 1, "surface_form": "世界", "pos": "名詞", "pos_detail_1": "一般", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "世界", "reading": "セカイ", "pronunciation": "セカイ" }, { "word_id": 92880, "word_type": "KNOWN", "word_position": 3, "surface_form": "を", "pos": "助詞", "pos_detail_1": "格助詞", "pos_detail_2": "一般", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "を", "reading": "ヲ", "pronunciation": "ヲ" }, { "word_id": 224280, "word_type": "KNOWN", "word_position": 4, "surface_form": "リード", "pos": "名詞", "pos_detail_1": "サ変接続", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "リード", "reading": "リード", "pronunciation": "リード" }, { "word_id": 3011740, "word_type": "KNOWN", "word_position": 7, "surface_form": "する", "pos": "動詞", "pos_detail_1": "自立", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "サ変・スル", "conjugated_form": "基本形", "basic_form": "する", "reading": "スル", "pronunciation": "スル" }, { "word_id": 230, "word_type": "UNKNOWN", "word_position": 9, "surface_form": "ワークプレイス・イノベーション・プラットフォーム", "pos": "名詞", "pos_detail_1": "一般", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "*" }, { "word_id": 90940, "word_type": "KNOWN", "word_position": 33, "surface_form": "。", "pos": "記号", "pos_detail_1": "句点", "pos_detail_2": "*", "pos_detail_3": "*", "conjugated_type": "*", "conjugated_form": "*", "basic_form": "。", "reading": "。", "pronunciation": "。" } ]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37739/745aa2e4-376c-abe3-cf0d-f816afb56671.png)

* ね、簡単でしょう？


# おわりに
## 次回予告
* ひとまず WEB ビューアに JSON データを表示させただけ！　というところで終わっているので、次はもう少し見た目を整えるところに手を着けます
* というわけで後編記事は以下となります
  * [FileMaker + kuromoji.js + Gird.js で形態素解析した後の json データを簡単にリスト表示化](https://qiita.com/Hi_Noguchi/items/1088e8239d2eb9e7f585)

## 感想
* 形態素解析のやり方は色々あると思いますが、インターネット環境があるのが概ね前提の世の中なので CDN で使えてしまうのがまあよろしかろうなのではないでしょうか
  * 辞書ファイルをローカルリソースとして使おうとすると色々面倒くなったので避けた
* `JSON.stringify(result, null, 2)` ってわざわざ書いて spacer の定義しても見た目が変わらず、「アレーなんだろー」って思ってるのですが、なんでだろ
  * ちなみに `"<br>"` と書くと改行として表示反映されるのですが……
  * 何か WEB ビューア環境ならではの特殊事情？？