More Related Content
Similar to Fess/Elasticsearchを使った業務で使える?全文検索への道 (20)
More from Shinsuke Sugaya (13)
Fess/Elasticsearchを使った業務で使える?全文検索への道
- 2. DBFluteフェス 2017
■ 名前: 菅谷信介
■ オープンソース活動:
➔ Fess, DBFlute関連, Apache PredictionIO,...
■ Blog: http://www.chazine.com/
■ Twitter: https://twitter.com/shinsuke_sugaya/
■ DBFluteフェスのこの枠で話すのは3回目…
自己紹介
2
- 6. DBFluteフェス 2017
■ OSSの分散リアルタイム検索&分析エンジン
■ 特徴
➔ドキュメント指向な検索エンジン(Apache Lucene)
➔RESTfulなAPI
➔スキーマフリー
➔分散システム (高可用性、スケールアウト)
➔プラグインによる拡張
■ DBFlute的に使うならESFluteも
➔https://github.com/lastaflute/lastaflute-example-waterfront/
Elasticsearchとは
6
- 13. DBFluteフェス 2017
{
"from" : 0,
"size" : 20,
"timeout" : "10000ms",
"query" : {
"bool" : {
"must" : [
{
"function_score" : {
"query" : {
"bool" : {
"should" : [
{
"match_phrase" : {
"title" : {
"query" : "テスト",
"slop" : 0,
"boost" : 0.2
}
}
},
{
"match_phrase" : {
"content" : {
"query" : "テスト",
"slop" : 0,
"boost" : 0.1
}
}
},
{
"match_phrase" : {
"title_ja" : {
"query" : "テスト",
"slop" : 0,
"boost" : 1.0
}
}
},
{
"match_phrase" : {
"content_ja" : {
"query" : "テスト",
"slop" : 0,
"boost" : 0.5
}
}
},
{
"match_phrase" : {
"title_en" : {
"query" : "テスト",
"slop" : 0,
"boost" : 1.0
}
}
},
13
{
"match_phrase" : {
"content_en" : {
"query" : "テスト",
"slop" : 0,
"boost" : 0.5
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
"functions" : [
{
"filter" : {
"match_all" : {
"boost" : 1.0
}
},
"field_value_factor" : {
"field" : "boost",
"factor" : 1.0,
"modifier" : "none"
}
}
],
"score_mode" : "multiply",
"max_boost" : 3.4028235E38,
"boost" : 1.0
}
}
],
"filter" : [
{
"bool" : {
"should" : [
{
"term" : {
"role" : {
"value" : "1guest",
"boost" : 1.0
}
}
},
{
"term" : {
"role" : {
"value" : "Rguest",
"boost" : 1.0
}
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
}
],
"disable_coord" : false,
"adjust_pure_negative" : true,
"boost" : 1.0
}
},
・
・
・
実際にはもっと長い…
Fessの検索クエリー
- 20. DBFluteフェス 2017
■ 構造的なQuery DSLを利用
■ HTTPまたはTransportでリクエスト
■ 様々なクエリーをサポート(aggs, geo,...)
検索クエリー
20
$ curl -XPOST ‘localhost:9200/company/_search -d ‘{
“query” : {
"match_phrase" : {
"content" : "fess"
}
},
“size”: 10
}
- 22. DBFluteフェス 2017
■ 解析された文字列にマッチするクエリー
➔ 全文検索で利用
➔ Match〜QueryはAnalyzerが適用される
■ 解析された文字列にマッチするので、lowercaseさ
れるならfluteはFluteにも一致する
➔ フレーズとしてはマッチしない
➔ 日本語bi-gramでは期待通りの結果にならない
Match Query
{
"query": {
"match": {
"product_name": "flute"
}
}
}
22
- 23. DBFluteフェス 2017
■ 解析された文字列のフレーズでマッチする
➔ タームの順番も含めて一致する
➔ 日本語の場合、ほぼこのクエリーを利用する
➔ Match Queryの場合、並び順に関係なく、ヒットする
➔ Match Queryでもphase指定で検索可能
Match Phrase Query
{
"query": {
"match_phrase": {
"product_name": "Low Price Flute"
}
}
}
23
- 24. DBFluteフェス 2017
■ 指定された値にマッチするクエリー
➔ テキスト解析はされず、値そのものにマッチする
➔ 区分値など、値のまま、インデックスしたものの検索
➔ keyword型のフィールドに対して利用
➔ Analyzerが適用されない
Term Query
{
"query": {
"term": {
"product_handle_code": {
"value": "FLUTE-01"
}
}
}
}
24
- 25. DBFluteフェス 2017
■ 前方一致のクエリー
➔ Term Queryの前方一致検索版
➔ テキスト解析されないフィールドで利用する
Prefix Query
{
"query": {
"prefix": {
"product_category": {
"value": "Ins"
}
}
}
}
25
- 26. DBFluteフェス 2017
■ 範囲指定検索
➔ 数値や日付を範囲指定する場合に利用する
➔ gt, gte, lt, lteで範囲を指定
Range Query
{
"query": {
"range": {
"latest_purchase_date": {
"gte": "2017-11-01",
"lte": "2017-11-30"
}
}
}
}
26
- 27. DBFluteフェス 2017
■ and/or/not条件を合成するクエリー
➔ and条件: mustで指定する(複数指定可能)
➔ or条件: shouldで指定する(複数指定可能)
➔ not条件: mustNotで指定する(複数指定可能)
➔ 絞り込み条件: filterで指定する(複数指定可能)
Bool Query
{
"query": {
"bool": {
"must": [...],
"should": [...],
"must_not": [...],
"filter": [...]
}
}
}
27
- 28. DBFluteフェス 2017
■ スコアを調整するクエリー
➔ functionsにマッチしたものをもとにスコアを変える
➔ queryには通常の検索条件を指定する
Function Score Query
{
"query": {
"function_score": {
"query": { ...ここに通常の条件を書く ... },
"functions": [
{
"filter": {
"match": {"test": "cat"} ←スコアを調整したい条件
},
"weight": 42
}
]
}
}
}
28
- 29. DBFluteフェス 2017
■ 検索時に集計処理も同時に行う
➔ 統計情報とかヒストグラムとか
➔ ファセットとかドリルダウンとか
Aggregation
29
{
"query": { ...検索条件... },
"aggs": {
"category": {
"terms": {
"field": "product_category",
"size": 10
}
}
}
}
- 30. DBFluteフェス 2017
■ フィールド値が範囲内にある件数を取得する
➔ Rangeが返却される
Range Aggregation
{
"query": { ...検索条件...},
"aggs": {
"price": {
"range": {
"field": "price",
"ranges": [
{
"from": 1000,
"to": 5000
},
…集計したい範囲の条件を記述...
]
}
}
}
}
30
- 31. DBFluteフェス 2017
■ 指定した単語が含まれる件数を取得する
➔ Termsが返却される
➔ 含まれる単語と件数が取得できる
Terms Aggregation
{
"query": { ...検索条件... },
"aggs": {
"category": {
"terms": {
"field": "product_category",
"size": 10
}
}
}
}
31
- 32. DBFluteフェス 2017
■ 指定したフィルタで項目を絞り込む
➔ 子のAggregationをフィルタするときに利用
■
➔
➔
Filter Aggregation
{
"query": { ...検索条件... },
"aggs": {
"handle_code": {
"filter": {
"term": { "product_handle_code": "FLUTE-01" }
},
"aggs": { ←フィルタされたあとの結果に対してのアグリゲーションを記述
"category": {
"terms": {
"field": "product_category"
}
}
}
}
}
}
32
- 33. DBFluteフェス 2017
■ 文字列: keyword, text
■ 数値: long, integer, short, byte, double, float,
half_float, scaled_float
■ 日付: date
■ 論理値: boolean
■ バイナリ: binary
■ 範囲: integer_range, float_range, double_range,
date_range
■ その他: object, geo_point, geo_shape, ip,
completion, token_count, …(独自定義も可能)
基本的な型
33
- 42. DBFluteフェス 2017
■ 全各言語用に様々なAnalyzerが必要
➔日本語だとKuromojiとか
■ 言語固有とbi-gramの2つのインデックス作成
➔日本語なら形態素解析とbi-gramの2種類
➔or検索(boolのshould等)をする
■ Fessでは多言語の設定を利用
➔いろいろと書いてあるので必要なところ参考に
https://github.com/codelibs/fess/blob/11.4.x/src/main/resources/fess_indices/fess.json
■ さらにFessでは言語自動判定も利用
多言語での検索
42
- 46. DBFluteフェス 2017
■ Google Search Applianceが保有する機能なので
普通に要求される場合が多い
■ Analyzerで同義語辞書で対応可能な場合もある
➔リアルタイムな反映が求められると☓
■ 関連クエリーと同等なものを作るしかない
➔Fessでは実装済み
➔関連コンテンツ的な機能もあったり…
関連クエリー
46
- 50. DBFluteフェス 2017
■ クロールとは別に画像生成処理を実行
■ HTMLであればページ内で指定された画像
➔metaタグのthumbnailかog:imageなど
➔ページ内のimgタグで正方形に近い画像など
➔PhantomJSなどでがんばる必要はない
■ PDFであればImageMagickのconvertコマンド
■ MS Officeはunoconvとconvertの合せ技
サムネイル画像
50
- 77. DBFluteフェス 2017
■ 検索システムを作るのもけっこう大変です
■ Lucene/Elasticsearchを直接使わなくても良い場合が
ほとんどでは?
➔ Fessを使ってください!(たぶんFessに任せたほうが楽)
➔ DB連携もJDBCでSQLを書くだけです
➔ 検索結果はJSONで取得できます
■ 検索自体を作りたい場合はLuceneやElasticsearchを
直接使うのが良いと思います
まとめ
77