概要
elasticsaerchで検索クエリで、取得したいfieldsを指定して投げるときの注意点という名の個人用備忘録。
結論
2016/07/07 修正
そもそも、クエリでfields指定するよりは、_sourceからフィルタリングして取れないかを検討する。
どうしても、クエリでfieldsを使いたいんや、という場合は・・・
(2.3だと、store:trueとしていないstringのフィールドでもfieldsでとれていた。)
- elasticsearch5.0以降で、クエリでfieldsを指定したいときは、mapping定義でstore:trueを入れておく
- stored_fieldsだとUnknown key for a START_ARRAY in [stored_fields].というエラーになった・・・
試した環境
製品 | バージョン |
---|---|
elasticsearch | 5.0.0-alpha4 |
kibana | 5.0.0-alpha4 |
elasticsearchはalpineをベースにしたDockerイメージで動かす。
ドキュメントの確認
Search and Query DSL changes
Search and Query DSL changesによると、fields parameterのところには、こんな風に書いてある
The fields parameter has been replaced by stored_fields. The stored_fields parameter will only return stored fields — it will no longer extract values from the _source.
たぶん、こういうことだと理解した。
- fieldsパラメータは、stored_fieldsに置き換えられた(ので、そっちを使うと良いよ)
- stored_fieldsパラメータは、storeされたフィールドしか返さないよ
- stored_fieldsパラメータは、_sourceフィールドから(結果を)抽出するわけじゃないよ
stored_fieldsの確認
Fieldsを確認しますと、また気になる記述があります。
The stored_fields parameter is about fields that are explicitly marked as stored in the mapping, which is off by default and generally not recommended. Use source filtering instead to select subsets of the original source document to be returned.
mappingでstoredと設定されたものだけが対象だよ。デフォルトだとオフになっているから、source filteringを使うと良いかもねかもねそうかもね。
source filterringの確認
Source Filteringで、sourceのフィルタリング方法を確認しておきます。
いざ、実践
kibanaにあるConsoleを使っていろいろテストしてみます。
テストデータの生成
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"title": {
"type": "text"
},
"first_name": {
"type": "text",
"store": true
},
"last_name": {
"type": "text",
"store": true
}
}
}
}
}
PUT my_index/my_type/1
{
"title": "Mr",
"first_name": "Barry",
"last_name": "White"
}
インデックスの確認
GET my_index/_search
{
"query" : {
"match_all": {}
}
}
検索結果
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1,
"_source": {
"title": "Mr",
"first_name": "Barry",
"last_name": "White"
}
}
]
}
}
fieldsを指定する
storeを指定していないフィールドの場合
store: trueとしなかった、titleフィールドを指定してみると、こんな結果になります。
クエリ
GET my_index/_search
{
"query" : {
"match_all": {}
},
"fields": ["title"]
}
結果がこちら。titleがどこにもありませんが、1件ヒットしていることが確認できます。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1
}
]
}
}
storeを指定したフィールドの場合
クエリ
GET my_index/_search
{
"query" : {
"match_all": {}
},
"fields": ["first_name", "last_name"]
}
結果がこちら。先ほどと異なり、first_nameとlast_nameが結果に含まれていることが確認できました。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1,
"fields": {
"last_name": [
"White"
],
"first_name": [
"Barry"
]
}
}
]
}
}
stored_fieldsを指定する
うまく結果が得られたfieldsでのクエリを少し編集して、fieldsをstored_fieldsに変えました。
GET my_index/_search
{
"query" : {
"match_all": {}
},
"stored_fields": ["first_name", "last_name"]
}
結果がこちら。悲しいパースエラー。
{
"error": {
"root_cause": [
{
"type": "parsing_exception",
"reason": "Unknown key for a START_ARRAY in [stored_fields].",
"line": 5,
"col": 20
}
],
"type": "parsing_exception",
"reason": "Unknown key for a START_ARRAY in [stored_fields].",
"line": 5,
"col": 20
},
"status": 400
}
sourceのfilterringを使う
store:trueを指定していなかったtitleと指定したlast_nameの2つを指定してみます。
GET my_index/_search
{
"query" : {
"match_all": {}
},
"_source": ["title", "last_name"]
}
結果がこちら。_sourceの中で指定したフィールドに絞られて結果が得られていることが確認できました。
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1,
"_source": {
"last_name": "White",
"title": "Mr"
}
}
]
}
}
おまけ
2.3系でfieldsを試したときのsense
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"title": {
"type": "string"
},
"first_name": {
"type": "string",
"store": true
},
"last_name": {
"type": "string",
"store": true
}
}
}
}
}
PUT my_index/my_type/1
{
"title": "Mr",
"first_name": "Barry",
"last_name": "White"
}
GET my_index/_search
{
"query" : {
"match_all": {}
},
"fields": ["title", "last_name"]
}
これで、結果はtitleとlast_nameと両方入る形。
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 1,
"hits": [
{
"_index": "my_index",
"_type": "my_type",
"_id": "1",
"_score": 1,
"fields": {
"title": [
"Mr"
],
"last_name": [
"White"
]
}
}
]
}
}