雑文発散

«前の日記(2016-12-14) 最新 次の日記(2016-12-16)» 編集
過去の日記

2016-12-15 [長年日記]

[Crowi] Crowi を Elasticsearch 5.x で動かしたい #2

昨日からの続き。昨日の修正内容が Elasticseach 2.x でもそのまま動くのか?という検証をしてみた。

Docker で Elasticsearch 2.4.2 のコンテナを立ち上げて、試してみた。 curl localhost:9201 で見える情報はこんな感じ。

{
  "name" : "Dreadknight",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "7RkgJy0wR-m8zp4y8eLeeg",
  "version" : {
    "number" : "2.4.2",
    "build_hash" : "161c65a337d4b422ac0c805f284565cf2014bb84",
    "build_timestamp" : "2016-11-17T11:51:03Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.2"
  },
  "tagline" : "You Know, for Search"
}

kuromoji も入れている。

% curl localhost:9201/_cat/plugins
Dreadknight analysis-kuromoji 2.4.2 j

動作検証するべきパターンはこんな感じだと思って、検証し始めたところ、2 番でまずコケた。

# 結果 ESバージョン 状態 検証動作
1 2.4.2 新規 インデックス作成ができるか?
2 × 2.4.2 新規 検索ができるか?
3 2.4.2 既存データあり (インデックス再構築前に)検索ができるか?
4 2.4.2 既存データあり インデックス作成ができるか?
5 2.4.2 既存データあり 検索ができるか?
6 5.1.1 新規 インデックス作成ができるか?
7 5.1.1 新規 検索ができるか?
8 -- 5.1.1 既存データあり このパターンは対象外

出力されていたエラーメッセージには、"unknown search element [stored_fields]" と出ていた。

{
  "type": "search_parse_exception",
  "reason": "failed to parse search source. unknown search element [stored_fields]",
  "line": 1,
  "col": 18
}

stored_fields は昨日 fields から書き換えたところなので、もう早速この修正だと Elasticsearch 2.4 では NG だということが分かった。ここでパッと思いつく対応としては「Elasticsearch のバージョンにより投げるクエリを変更する」というもの。でも、そういう処理は今のところ TODO 状態だ(笑)

SearchClient.prototype.checkESVersion = function() {
  // TODO
};

そこで、ちょっと思いついた。そもそも、この stored_fields もしくは fields は一体何を実現するためのクエリなのか?と。そこを理解していなかった。

fields を指定した場合のレスポンス例。

{
  "took": 13,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.03262724,
    "hits": [
      {
        "_index": "crowi",
        "_type": "pages",
        "_id": "58507dcc0509e44224a4373c",
        "_score": 0.03262724,
        "fields": {
          "path": [
            "/user/suzuki/メモ/2016/12/14/日本語入り"
          ]
        }
      }
    ]
  }
}

fields を外した場合のレスポンス例。

{
  "took": 53,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.03262724,
    "hits": [
      {
        "_index": "crowi",
        "_type": "pages",
        "_id": "58507dcc0509e44224a4373c",
        "_score": 0.03262724,
        "_source": {
          "path": "/user/suzuki/メモ/2016/12/14/日本語入り",
          "body": "# 日本語入り


吾輩わがはいは猫である。名前はまだ無い。

どこで生れたかとんと見当けんとうがつかぬ。何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪どうあくな種族であったそうだ。この書生というのは時々我々を捕つかまえて煮にて食うという話である。

しかしその当時は何という考もなかったから別段恐しいとも思わなかった。ただ彼の掌てのひらに載せられてスーと持ち上げられた時何だかフワフワした感じがあったばかりである。掌の上で少し落ちついて書生の顔を見たのがいわゆる人間というものの見始みはじめであろう。この時妙なものだと思った感じが今でも残っている。第一毛をもって装飾されべきはずの顔がつるつるしてまるで薬缶やかんだ。


その後ご猫にもだいぶ逢あったがこんな片輪かたわには一度も出会でくわした事がない。のみならず顔の真中があまりに突起している。そうしてその穴の中から時々ぷうぷうと煙けむりを吹く。どうも咽むせぽくて実に弱った。これが人間の飲む煙草たばこというものである事はようやくこの頃知った。",
          "username": "suzuki",
          "comment_count": 0,
          "bookmark_count": 0,
          "like_count": 0,
          "created_at": "2016-12-13T23:01:32.770Z",
          "updated_at": "2016-12-13T23:01:32.982Z"
        }
      }
    ]
  }
}

fields 指定がないと、_source の内容が丸ごと返ってきている。丸ごと返ってくるのは無駄な場合もあるので、その抑制のために fields 指定をしているのかな。SQL で SELECT * FROM ... の代わりに SELECT id, name FROM ... みたいにするように。

もし、「丸ごとデータの抑制」のための fields 指定だったら、 "_source": "path" のようにして、必要な _source だけに絞り込むこともできる。

{
  "took": 14,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.03262724,
    "hits": [
      {
        "_index": "crowi",
        "_type": "pages",
        "_id": "58507dcc0509e44224a4373c",
        "_score": 0.03262724,
        "_source": {
          "path": "/user/suzuki/メモ/2016/12/14/日本語入り"
        }
      }
    ]
  }
}

fields を指定していた場合は、 hits.fields という項目が返ってきている。これを検索結果として利用しているかどうかで、上記の _source による抑制に切り替えても良さそうな気はする。

ここはもうちょっとコードを追わないと分からないなぁ。ということで、続く。