OpenSearchのマッピングも無事完了し、データ投入をしようとした時にエラーになってハマったのでその覚書です。
前提
実行環境はOpenSearch DashbordsのDev Toolsです。
HTTPなリクエストを投げても結果は同じになると思います。
準備編
インデックスを作ってマッピング定義をします。
わかりやすさのために本質と関係のない箇所は簡略化しています。
PUT blog
{
"settings": {
"analysis": {
"analyzer": {
"ja_analyzer": {
"type": "custom",
"char_filter":[
"icu_normalizer"
],
"tokenizer": "kuromoji_tokenizer",
"filter": [
"kuromoji_baseform",
"kuromoji_part_of_speech",
"ja_stop",
"kuromoji_number",
"kuromoji_stemmer"
]
}
}
}
},
"mappings": {
"properties": {
"title": {
"type": "text",
"fielddata": true,
"analyzer": "ja_analyzer",
"search_analyzer": "ja_analyzer"
},
"thumbnail": {
"properties": {
"image": {
"type": "keyword"
},
"alt": {
"type": "keyword"
}
}
},
"content": {
"type": "text",
"fielddata": true,
"analyzer": "ja_analyzer",
"search_analyzer": "ja_analyzer"
},
"category": {
"type": "byte"
}
}
}
}
データ投入
さて、いよいよ本題のデータ投入です。
データ投入するにはデータを1件ずつ投入していく方法と、まとめて投入する方法があります。
1件ずつであればこんな感じ。
POST blog/_doc/1
{
"title": "記事のタイトル1",
"thumbnail.image": "/images/category1.png",
"thumbnail.alt": "カテゴリ1の記事",
"content": "記事の本文1",
"category": 1
}
まとめてならBulkを使ってこんな感じ。
対象のインデックス指定とデータを交互に。
POST blog/_bulk
{
"index": {
"_index": "blog",
"_id": "1"
}
}
{
"title": "記事のタイトル1",
"thumbnail.image": "/images/category1.png",
"thumbnail.alt": "カテゴリ1の記事",
"content": "記事の本文1",
"category": 1
}
{
"index": {
"_index": "blog",
"_id": "2"
}
}
{
"title": "記事のタイトル2",
"thumbnail.image": "/images/category1.png",
"thumbnail.alt": "カテゴリ1の記事",
"content": "記事の本文2",
"category": 1
}
で登録できると思ってました。
思っていたんですが、Bulkは流すとエラーが起きてしまいました。
{
"error" : {
"root_cause" : [
{
"type" : "json_e_o_f_exception",
"reason" : "Unexpected end-of-input: expected close marker for Object (start marker at [Source: (byte[])"{"; line: 1, column: 1])\n at [Source: (byte[])"{"; line: 1, column: 2]"
}
],
"type" : "json_e_o_f_exception",
"reason" : "Unexpected end-of-input: expected close marker for Object (start marker at [Source: (byte[])"{"; line: 1, column: 1])\n at [Source: (byte[])"{"; line: 1, column: 2]"
},
"status" : 400
}
なんだこれ。。。
json_e_o_f_exception
ってありますが、よく見るとreasonにUnexpected end-of-input: expected close marker for Object
とあるので、JSONのフォーマット間違っているようです。
目視する限り間違っていないように見えます。
ここは自分の目を疑って、parseしてみます。
http://json.parser.online.fr/
こちらにペタっと貼り付けて、頭とお尻を[
]
で囲って配列にします。
結果は、問題なし。
改行コードがLFになっていたのでこれがダメなのか?と思ってCRLFに変換してみても状況変わらず。
出力されたメッセージには[Source: (byte[])\"{\"; line: 1, column: 1])
とあり、1行目が問題だと言われているので、1行目から改行外してみます。
POST blog/_bulk
{"index": {"_index": "blog","_id": "1"}}
{
"title": "記事のタイトル1",
"thumbnail.image": "/images/category1.png",
"thumbnail.alt": "カテゴリ1の記事",
"content": "記事の本文1",
"category": 1
}
{
"index": {
"_index": "blog",
"_id": "2"
}
}
{
"title": "記事のタイトル2",
"thumbnail.image": "/images/category1.png",
"thumbnail.alt": "カテゴリ1の記事",
"content": "記事の本文2",
"category": 1
}
別のエラーが返ってきました。
{
"error" : {
"root_cause" : [
{
"type" : "illegal_argument_exception",
"reason" : "Malformed action/metadata line [3], expected START_OBJECT but found [VALUE_STRING]"
}
],
"type" : "illegal_argument_exception",
"reason" : "Malformed action/metadata line [3], expected START_OBJECT but found [VALUE_STRING]"
},
"status" : 400
}
今度は3行目のフォーマット違反だと。
オブジェクトが始まらないといけないのに文字列が始まってるよ。。。ここも改行コードが悪さしてるの?
ということで、こちらも削ってみます。
POST blog/_bulk
{"index": {"_index": "blog","_id": "1"}}
{"title": "記事のタイトル1","thumbnail.image": "/images/category1.png","thumbnail.alt": "カテゴリ1の記事","content": "記事の本文1","category": 1
}
{
"index": {
"_index": "blog",
"_id": "2"
}
}
{
"title": "記事のタイトル2",
"thumbnail.image": "/images/category1.png",
"thumbnail.alt": "カテゴリ1の記事",
"content": "記事の本文2",
"category": 1
}
また違うエラーになりました。
{
"error" : {
"root_cause" : [
{
"type" : "json_parse_exception",
"reason" : "Unexpected close marker '}': expected ']' (for root starting at [Source: (byte[])"}"; line: 1, column: 0])\n at [Source: (byte[])"}"; line: 1, column: 2]"
}
],
"type" : "json_parse_exception",
"reason" : "Unexpected close marker '}': expected ']' (for root starting at [Source: (byte[])"}"; line: 1, column: 0])\n at [Source: (byte[])"}"; line: 1, column: 2]"
},
"status" : 400
}
今度はオブジェクトの終了がないと。
データを定義しているオブジェクトの終了だけ次の行にいるので、ここも改行外してみます。
POST blog/_bulk
{"index": {"_index": "blog","_id": "1"}}
{"title": "記事のタイトル1","thumbnail.image": "/images/category1.png","thumbnail.alt": "カテゴリ1の記事","content": "記事の本文1","category": 1}
{
"index": {
"_index": "blog",
"_id": "2"
}
}
{
"title": "記事のタイトル2",
"thumbnail.image": "/images/category1.png",
"thumbnail.alt": "カテゴリ1の記事",
"content": "記事の本文2",
"category": 1
}
また最初のエラーに戻りました。
エラーの行数まで同じ。
なんでやねん!とツッコまざるを得ない。。。
ですが、おそらく2つ目のデータの塊(インデックス指定とデータのセット)が1つ目の修正前と同じ状態なのでこちらも改行を取っ払えばよさそう。
POST blog/_bulk
{"index": {"_index": "blog","_id": "1"}}
{"title": "記事のタイトル1","thumbnail.image": "/images/category1.png","thumbnail.alt": "カテゴリ1の記事","content": "記事の本文1","category": 1}
{"index": {"_index": "blog","_id": "2"}}
{"title": "記事のタイトル2","thumbnail.image": "/images/category1.png","thumbnail.alt": "カテゴリ1の記事","content": "記事の本文2","category": 1}
やっと、無事登録できました。
長かった。
結論/解決策
Bulkでデータ投入する際にはJSONだからと自由に整形せず、
・インデックスの指定
・データの指定
この2つをそれぞれ1行にまとめて繰り返しましょう。
ドキュメントのどこかに書いてあるのかもしれませんが、完全見落とし。。。
しかし、JSONだから改行読み飛ばして処理してくれよー