Elasticsearchのcopy_toを使うと複数のフィールド値を1つのフィールドにまとめることができます。
公式サイトの例だと first_name、last_nameのフィールドからfull_nameのフィールドにcopy_toで値をコピーしておいて、full_nameフィールドだけで名前検索っていう例がのってます。
おもしろいなぁとおもったのが、マッピング定義としてはfull_nameフィールドが存在してて、そこに値をコピーしてるんだけど、_search結果の _sourceにはfull_nameが入ってこないこと。
公式の例のとおりindex作成
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"first_name": {
"type": "text",
"copy_to": "full_name"
},
"last_name": {
"type": "text",
"copy_to": "full_name"
},
"full_name": {
"type": "text"
}
}
}
}
}
データ投入して検索。
PUT my_index/_doc/1
{
"first_name": "Ryuji",
"last_name": "AMANO"
}
GET my_index/_search
{
"query": {
"match": {
"full_name": "Ryuji"
}
}
}
// 結果
{
"took": 53,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "my_index",
"_type": "_doc",
"_id": "1",
"_score": 0.2876821,
"_source": {
"first_name": "Ryuji",
"last_name": "AMANO"
}
}
]
}
}
こんな感じで確かにcopy_toで保存したフィールドは_sourceには出力されません。
じゃ、full_nameに直接値をつっこんだら?
PUT my_index/_doc/2
{
"full_name": "Nobunaga ODA"
}
GET my_index/_search
{
"query": {
"match": {
"full_name": "ODA"
}
}
}
// 結果
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "my_index",
"_type": "_doc",
"_id": "2",
"_score": 0.2876821,
"_source": { // 今度はfull_nameが表示される。
"full_name": "Nobunaga ODA"
}
}
]
}
}
同じフィールドなのに表示されたり、表示されなかったりっていうのは 普段MySQLいじってる感覚からすると奇妙にも思えるんですが、 _source は、 PUT 等で登録された入力値だって思えばなんとなく納得できますかね。
PUTで直接full_nameに入れれば、_sourceにfull_nameありだし、copy_toでfull_nameにコピーしたときは、full_nameのインデックスに内部的に登録はされてるけど、_sourceでは無いってことかなと。