SlideShare a Scribd company logo
1 of 73
Download to read offline
ESFluteによるElasticsearchでの
O/Rマッパーを用いた開発
DBFluteフェス2016 1
DBFluteフェス 2016
■ 名前: 菅谷信介
■ オープンソース活動:
➔ Fess, DBFlute関連, Apache Portals, Codehaus,
Seasar2,...
■ Blog: http://www.chazine.com/
■ Twitter: https://twitter.com/shinsuke_sugaya/
自己紹介
2
DBFluteフェス 2016
■ ESFluteとは
■ Elasticsearchについて
■ ESFluteの使い方
アジェンダ
3
DBFluteフェス 2016
背景
4
DBFluteフェス 2016
■ 全文検索サーバFessでDBFluteを用いて開発
➔検索データはSolrで管理
➔設定データはデータベースで管理
■ SolrからElasticsearchに移行
➔この機会にDBをやめることを決断
➔DBがあると構築の手間が増える
■ 大量のBhvやCBを利用したコードが存在
➔工数が…
ESFlute誕生の背景
5
DBFluteフェス 2016
BhvやCBでElasticsearchに
アクセスできればよいのでは!
6
DBFluteフェス 2016
ESFluteとは
7
DBFluteフェス 2016
■ DBFluteのElasticsearch版
➔ CBやBhvが使えます
■ インデックス設定情報からソースの自動生成
■ Elasticsearch 1.7と2.xに対応
➔ 5.x系対応は近日対応予定
➔ バージョンごとにブランチ管理
■ DBFlute本体にバンドル
➔ 将来的には単独の配布にしたい
■ Exampleプロジェクト
https://github.com/lastaflute/lastaflute-example-waterfront
テストコードもあります!
ESFluteとは
8
DBFluteフェス 2016
Elasticsearchとは
9
DBFluteフェス 2016
■ OSSの分散リアルタイム検索&分析エンジン
■ 特徴
➔ドキュメント指向な検索エンジン(Apache Lucene)
➔RESTfulなAPI
➔スキーマフリー
➔分散システム (高可用性、スケールアウト)
➔プラグインによる拡張
Elasticsearchとは
10
DBFluteフェス 2016
(物理的な?)
構成要素
ESFlute的にはあまり気にしないで良いかも…
11
DBFluteフェス 2016
分散環境的な話…
■ 基本的な構成要素
➔ クラスタ
➔ ノード
➔ インデックス
➔ シャード
■ クラスタは複数のノードから構成される
■ クラスタは複数のインデックスを保持できる
■ インデックスは複数のシャードから構成される
■ シャードは1つのプライマリと複数のレプリカで構成
される
■ ノードは複数のシャードを保持できる
構成要素
12
DBFluteフェス 2016
構成要素
13
ノード1
ノード3
ノード2
ノード4
インデックス1
シャード1
インデックス1
シャード2
インデックス2
シャード2
インデックス1
シャード2
インデックス2
シャード1
インデックス1
シャード3
インデックス1
シャード1
インデックス2
シャード1
インデックス1
シャード4
インデックス1
シャード3
インデックス2
シャード2
インデックス1
シャード4
クラスタ
DBFluteフェス 2016
(論理的な?)
構成要素
ESFlute的には自動生成上、関係ある
14
DBFluteフェス 2016
■ インデックス単位にドキュメントが保存される
■ ドキュメントはType属性を持つ
➔ドキュメントはタイプに含まれる
■ 検索はインデックスとタイプを指定する
データ観点での構成要素
15
Type
Index
Cluster
Type
Type
Index
Type
DBFluteフェス 2016
■ ESFluteはDBFluteのようなO/Rマッパー
■ インデックスを1つのデータベースとして考える
■ タイプをテーブルとして考える
ESFluteでの構成要素の対応
16
Type
Index
Cluster
Type
Type
Index
Type
Table
DB
Table
Table
DB
Table
ESFlute DBFlute
DBFluteフェス 2016
17
基本的な操作
DBFluteフェス 2016
■ インデックス名を指定してPUTでリクエスト
$ curl -XPUT ‘localhost:9200/company -d ‘{
“settings”: {
…(Analyzer等のインデックス関連の指定)...
},
“mappings”: {
…(スキーマなど指定)...
}
}’
インデックス作成
18
DBFluteフェス 2016
■ PUT/POSTでJSONオブジェクトをリクエスト
■ パスは /インデックス名/タイプ名/ID
$ curl -XPUT ‘localhost:9200/company/employee/1’ -d ‘{
“employee_id”: ”00001”,
“first_name”: “Taro”,
“last_name”: “Suzuki”
}’
ドキュメントの追加
19
DBFluteフェス 2016
■ DELETEでリクエスト
■ パスは /インデックス名/タイプ名/ID
■ プラグイン導入してクエリーで削除も可能
$ curl -XDELETE ‘localhost:9200/company/employee/1’
ドキュメントの削除
20
DBFluteフェス 2016
■ 文字列: string
■ 数値: long, integer, short, byte, double, float
■ 日付: date
■ 論理値: boolean
■ バイナリ: binary
■ その他: object, geo_point, ip,...
ESFluteではバイナリやその他の型はまだ未対応
基本的な型
21
DBFluteフェス 2016
■ 文字列を解析して、索引を作る
■ 検索は索引から単語が含まれるIDリストを取得
転置インデックス
22
ID 文字列
1 東京スカイツリー
2 東京タワー
単語 IDリスト
東京 1, 2
スカイツリ 1
タワー 2
DBFluteフェス 2016
■ テキストを分解して単語群を生成する
■ CharFilter/Tokenizer/TokenFilterで構成される
■ Luceneのインターフェース
■ 組み合わせることで自由自在の解析可能
■ インデックスの生成時に設定する
「今日の天気は晴れです」
     ↓
「今日」「天気」「晴れ」
Analyzer
23
DBFluteフェス 2016
Analyzer
24
「東京スカイツリーの①番出口」
CharFilter (文字単位で変換)
TokenFilter (単語単位で変換)
Tokenizer (単語に分割)
「東京スカイツリーの1番出口」
「東京」「スカイツリー」「の」「1番」「出口」
「東京」「スカイツリ」「1番」「出口」
Analyzer
DBFluteフェス 2016
■ 構造的なQuery DSLを利用
■ HTTPまたはTransportでリクエスト
➔現時点ではESFluteはTransportを利用
■ 様々なクエリーをサポート(aggs, geo,...)
$ curl -XPOST ‘localhost:9200/company/_search -d ‘{
“query” : {
"match_phrase" : {
"content" : "fess"
}
},
“size”: 10
}
検索クエリー
25
DBFluteフェス 2016
ESFluteの設定
26
DBFluteフェス 2016
■ DBFluteの基本的な設定を作成
例(Mavenプロジェクトなら):
$ mvn dbflute:download
$ mvn dbflute:create-client
http://dbflute.seasar.org/ja/environment/setup/index.html
DBFluteの環境準備
27
DBFluteフェス 2016
■ ESFluteはインデックス情報を利用
■ Elasticsearchのインデックス情報をファイルに保存
する
$ curl -XGET localhost:9200/[index] >
dbflute_[project]/playes/index/[index].json
インデックス情報の保存
28
DBFluteフェス 2016
■ dbflute_[project]/dfprop/esfluteMap.dfprop
esfluteMap.dfprop
map:{
# base package of generated classes
; basePackage = org.docksidestage.esflute
# base path to JSON resource, URL or relative path
; basePath = ./playes/index ←インデックスの設定情報ファイルを置いておくディレクトリ
# settings for indexes
; indexMap = map:{
; maihama = map:{ ←インデックス名
; package = maihama
}
}
# version for elasticsearch's jar file (no version means latest)
; elasticsearchVersion = 2.3.0
}
29
DBFluteフェス 2016
■ DBFluteのFreeGenを実行
$ mvn dbflute:freegen
➔ [basePackage].[index]パッケージ以下にソースコードを自
動生成
➔ DB版同様、CBやBhv等が生成される
ソースコードの生成
30
DBFluteフェス 2016
必要に応じて…
コンポーネント定義
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//DBFLUTE//DTD LastaDi 1.0//EN"
"http://dbflute.org/meta/lastadi10.dtd">
<components>
<include path="esclient.xml"/>
<!-- The components of DBFlute Runtime. -->
<component name="behaviorCommandInvoker" class="org.dbflute.bhv.core.BehaviorCommandInvoker"/>
<!-- The components of Behavior. -->
<component name="userBhv" class="org.codelibs.fess.es.user.exbhv.UserBhv"/>
<component name="roleBhv" class="org.codelibs.fess.es.user.exbhv.RoleBhv"/>
<component name="groupBhv" class="org.codelibs.fess.es.user.exbhv.GroupBhv"/>
</components>
31
DBFluteフェス 2016
ESFluteで操作
32
DBFluteフェス 2016
■ Bhvインスタンスでinsert
➔ オプションで即時反映も可能
➔ 更新も同じ感じで
データの追加
@Resource
private ProductBhv productBhv;
…
Product product = new Product();
product.setProductDescription(form.productDescription);
product.setProductCategoryCode(form.productCategoryCode);
...
productBhv.insert(product, op -> {
op.setRefresh(true); // 即時反映
});
33
DBFluteフェス 2016
■ Bhvインスタンスでdelete
➔ オプションで即時反映も可能
➔ Delete By Queryも内部的にScrollで実現
データの削除
productBhv.selectByPK(form.productId).ifPresent(entity -> {
productBhv.delete(entity, op -> {
op.setRefresh(true);
});
}).orElse(() -> {
throw404("Not found the product: " + form.productId);
});
34
DBFluteフェス 2016
■ 各種検索クエリーに対応
➔ConditionBeanがQuery DSLを組み立てる
■ Aggregationにも対応
検索
35
DBFluteフェス 2016
検索
36
DBFluteフェス 2016
■ BhvでselectPage, selectList, selectByPK,
selectCount, selectEntity, selectCursorに対応
■ CBで検索条件を指定
➔ pagingやaddOrder〜も対応
■ 戻り値はDBFluteと同様
検索系メソッド
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.query().addOrderBy_Id_Asc();
cb.paging(5, 1);
});
37
DBFluteフェス 2016
■ 全件にマッチするクエリー
➔ count等で利用
Match All Query
38
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.query().addOrderBy_Id_Asc();
cb.paging(5, 1);
});
DBFluteフェス 2016
■ 解析された文字列にマッチするクエリー
➔ 全文検索で利用
■ 解析された文字列にマッチするので、以下のflute
はFluteにも一致する
➔ フレーズとしてはマッチしない
➔ 日本語bi-gramでは期待通りの結果にならない
Match Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductName_Match("flute");
cb.query().addOrderBy_Id_Asc();
cb.paging(5, 1);
});
39
DBFluteフェス 2016
■ 解析された文字列のフレーズでマッチする
➔ タームの順番も含めて一致する
➔ 日本語の場合、ほぼこのクエリーを利用する
➔ Match Queryの場合、並び順に関係なく、ヒットする
Match Phrase Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductName_MatchPhrase("Low Price Flute");
cb.query().addOrderBy_Id_Asc();
cb.paging(5, 1);
});
40
DBFluteフェス 2016
■ フレーズでの前方一致にマッチするクエリー
➔ Match Phraseの前方一致版クエリー
➔ 入力された文字列の最後の単語では前方一致を行う
Match Phrase Prefix Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductName_MatchPhrasePrefix("Low P", op -> {
op.maxExpansions(10);
});
cb.query().addOrderBy_Id_Asc();
cb.paging(5, 1);
});
41
DBFluteフェス 2016
■ 頻出単語を除外してマッチするクエリー
■ 頻度の指定が可能
➔ 以下の例だと、0.1%より多く登場する単語を除外
Common Terms Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductName_CommonTerms("What is Grand Piano", op -> {
op.cutoffFrequency(0.001f);
});
cb.query().addOrderBy_Id_Asc();
cb.paging(5, 1);
});
42
DBFluteフェス 2016
■ 検索クエリーを文字列で指定するクエリー
➔ サーチエンジンに利用
➔ Luceneの構文に従う
■ 入力によって幅広い検索が可能
➔ 範囲検索、あいまい検索、正規表現等
Query String Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().queryString("Flute OR Piano", op -> {
op.defaultField("product_name");
});
cb.query().addOrderBy_Id_Asc();
cb.paging(5, 1);
});
43
DBFluteフェス 2016
■ 指定された値にマッチするクエリー
➔ テキスト解析はされず、値そのものにマッチする
➔ 区分値など、値のまま、インデックスしたものの検索
➔ not_analyzedのフィールドに対して利用
➔ set〜_EqualはTerm Queryを利用
Term Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductHandleCode_Term("FLUTE-01", op -> {
op.queryName("exact_value");
});
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
44
DBFluteフェス 2016
■ Term Queryの複数指定版クエリー
➔ 複数の値にマッチする検索をする
➔ set〜_InScopeはTerms Queryを利用
Terms Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
ArrayList<String> terms = new ArrayList<>();
terms.add("piano");
terms.add("flute");
cb.query().setProductName_Terms(terms);
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
45
DBFluteフェス 2016
■ 範囲指定検索
➔ 数値や日付を範囲指定する場合に利用する
➔ 通常のCBと同様
Range Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setLatestPurchaseDate_GreaterEqual(
LocalDateTime.of(2014, 1, 1, 0, 0, 0));
cb.query().addOrderBy_LatestPurchaseDate_Asc();
cb.paging(5, 1);
});
46
DBFluteフェス 2016
■ フィールドに値が存在するものにマッチする
➔ 値があるものを検索する場合に利用する
■ 存在しないものを検索したい場合
➔ boolのmust_notのexistsクエリーを利用する
■ null値はElasticsearch上で設定可能
Exists Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductName_Exists();
cb.query().addOrderBy_ProductName_Asc();
cb.paging(5, 1);
});
47
DBFluteフェス 2016
■ 前方一致のクエリー
➔ Term Queryの前方一致検索版
➔ テキスト解析されないフィールドで利用する
Prefix Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductCategory_Prefix("Ins");
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
48
DBFluteフェス 2016
■ ワイルドカードによる検索
➔ Term Queryのワイルドカード検索版
➔ テキスト解析されないフィールドで利用する
Wildcard Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductCategoryCode_Wildcard("H?B");
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
49
DBFluteフェス 2016
■ 正規表現による検索
➔ Term Queryで正規表現を利用したい場合に利用する
➔ 遅い
Regexp Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductHandleCode_Regexp("[A-Z]{5}-<01-02>");
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
50
DBFluteフェス 2016
■ あいまい検索
➔ レーベンシュタイン距離による検索
➔ 類似する単語を見つける
Fuzzy Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setProductCategory_Fuzzy("Insturument");
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
51
DBFluteフェス 2016
■ and/or/notを合成するクエリー
➔ and条件: mustで指定する(複数指定可能)
➔ or条件: shouldで指定する(複数指定可能)
➔ not条件: mustNotで指定する(複数指定可能)
■ filter条件も設定可能
➔ and/or/notの前にフィルタ条件を指定する
Bool Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().bool((must, should, mustNot, filter) -> {
must.setProductName_Match("flute");
mustNot.setProductName_Match("gold");
});
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
52
DBFluteフェス 2016
■ スコアを調整するクエリー
➔ functionsにマッチしたものをもとにスコアを変える
➔ queryには通常の検索条件を指定する
Function Score Query
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().functionScore(query -> {
query.setProductCategory_Equal("MusicCD");
}, functions -> {
functions.filter(cq -> {
cq.setProductName_Match("street");
}, ScoreFunctionBuilders.weightFactorFunction(10.0f));
}, op -> {});
cb.paging(5, 1);
});
53
DBFluteフェス 2016
Aggregation
54
DBFluteフェス 2016
■ 検索時に集計処理も同時に行う
➔ ファセットとかドリルダウンとか
■ 集計結果はElasticsearchのインスタンスを利用
➔ 独自に生成するとメンテリスクがあるため
Aggregation
55
DBFluteフェス 2016
■ 平均値を集計する
➔ Avgのインスタンスが返却される
Avg Aggregation
56
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Avg();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Avg avg = (Avg) aggregations.get("regular_price");
assertEquals(353455.0, avg.getValue());
DBFluteフェス 2016
■ フィールドでユニークな項目数を取得する
➔ Cardinalityが返却される
Cardinality Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setProductCategory_Cardinality();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Cardinality cardinality = (Cardinality) aggregations.get("product_category");
assertEquals(3, cardinality.getValue());
57
DBFluteフェス 2016
■ 様々な統計的数値を得る
➔ ExtendedStatsが返却される
➔ 最大、最小、平均、分散、標準偏差等
Extended Stats Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_ExtendedStats();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
ExtendedStats extendedStats = (ExtendedStats) aggregations.get("regular_price");
assertEquals(353455.0, extendedStats.getAvg());
58
DBFluteフェス 2016
■ 最大値を取得する
➔ Maxが返却される
Max Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Max();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Max max = (Max) aggregations.get("regular_price");
assertEquals(4000000.0, max.getValue());
59
DBFluteフェス 2016
■ 最小値を取得する
➔ Minが返却される
Min Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Min();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Min min = (Min) aggregations.get("regular_price");
assertEquals(340.0, min.getValue());
60
DBFluteフェス 2016
■ 百分位数を計算する
➔ 小さい順に並べて、X%にある値を取得する
➔ 外れ値を検出するなど
➔ 以下ではRegularPriceの下位1%の位置に347.6
Percentiles Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Percentiles();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Percentiles percentiles = (Percentiles) aggregations.get("regular_price");
assertEquals(347.6, percentiles.percentile(1));
61
DBFluteフェス 2016
■ 百分位数における順位を計算する
➔ 指定した値のランクを取得する
➔ 以下ではRegularPriceが1000のときが23.125%
Percentile Ranks Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_PercentileRanks(op -> op.percentiles(1000, 10000));
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
PercentileRanks percentileRanks = (PercentileRanks) aggregations.get("regular_price");
assertEquals(23.125, percentileRanks.percent(1000));
62
DBFluteフェス 2016
■ 基本的な統計的数値を算出する
➔ Statsが返却される
➔ 項目数、最小値、最大値、平均値、合計値
Stats Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Stats();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Stats stats = (Stats) aggregations.get("regular_price");
assertEquals(353455.0, stats.getAvg());
63
DBFluteフェス 2016
■ 合計値を取得する
➔ Sumが返却される
Sum Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Sum();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Sum sum = (Sum) aggregations.get("regular_price");
assertEquals(7069100.0, sum.getValue());
64
DBFluteフェス 2016
■ フィールドに値を持つ件数を取得する
➔ ValueCountが返却される
➔ スクリプトによる指定も可能
Value Count Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setProductCategory_Count();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
ValueCount valueCount = (ValueCount) aggregations.get("product_category");
assertEquals(20, valueCount.getValue());
65
DBFluteフェス 2016
■ 指定したフィルタで項目を絞り込む
➔ 子のAggregationをフィルタするときに利用
■
➔
➔
Filter Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().filter("filter", cq -> cq.setProductName_Equal("flute"),
op -> {}, aggs -> aggs.setRegularPrice_Avg());
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Filter filter = (Filter) aggregations.get("filter");
Avg avg = (Avg) filter.getAggregations().get("regular_price");
assertEquals(1516666.6666666667, avg.getValue());
66
DBFluteフェス 2016
■ ヒストグラムを生成する
➔ Histogramが返却される
Histogram Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().setRegularPrice_LessThan(2000);
cb.aggregation().setRegularPrice_Histogram(op -> {
op.interval(200).extendedBounds(0L, 2000L);
}, aggs -> {});
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Histogram histogram = (Histogram) aggregations.get("regular_price");
assertEquals(11, histogram.getBuckets().size());
assertEquals(3L, histogram.getBuckets().get(1).getDocCount());
67
DBFluteフェス 2016
■ フィールドに値が存在しない項目を得る
➔ Missingが返却される
Missing Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Missing();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Missing missing = (Missing) aggregations.get("regular_price");
assertEquals(0, missing.getDocCount());
68
DBFluteフェス 2016
■ フィールド値が範囲内にある件数を取得する
➔ Rangeが返却される
Range Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setRegularPrice_Range(op -> {
op.addUnboundedFrom("all", 0)
.addRange("average", 1000, 5000)
.addUnboundedTo("cheap", 1000);
}, aggs -> {});
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Range range = (Range) aggregations.get("regular_price");
assertEquals(4, range.getBuckets().get(0).getDocCount());
69
DBFluteフェス 2016
■ 指定した単語が含まれる件数を取得する
➔ Termsが返却される
➔ 含まれる単語と件数が取得できる
Terms Aggregation
PagingResultBean<Product> list1 = productBhv.selectPage(cb -> {
cb.query().matchAll();
cb.aggregation().setProductName_Terms();
cb.query().addOrderBy_ProductHandleCode_Asc();
cb.paging(5, 1);
});
EsPagingResultBean<Product> list2 = (EsPagingResultBean<Product>) list1;
Aggregations aggregations = list2.getAggregations();
Terms terms = (Terms) aggregations.get("product_name");
List<Bucket> buckets = terms.getBuckets();
assertEquals("100g", buckets.get(0).getKey());
assertEquals(4, buckets.get(0).getDocCount());
70
DBFluteフェス 2016
■ Elasticsearch 5.0対応
■ geo_point対応
■ ネストしたプロパティへの対応
■ multifieldの対応
■ join対応
■ HTTPでの接続方法
■ 適切でない利用方法やクエリを通知する
今後のタスク
71
DBFluteフェス 2016
まとめ
72
DBFluteフェス 2016
■ ESFluteでElasticsearchを利用できる
■ DBFluteのように実装できる
■ インデックス情報からソースは自動生成
■ DBFluteにバンドル済みなので、すぐに利用可能
まとめ
73

More Related Content

What's hot

What's hot (20)

SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
ヤフー社内でやってるMySQLチューニングセミナー大公開
ヤフー社内でやってるMySQLチューニングセミナー大公開ヤフー社内でやってるMySQLチューニングセミナー大公開
ヤフー社内でやってるMySQLチューニングセミナー大公開
 
GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出GitLab から GitLab に移行したときの思い出
GitLab から GitLab に移行したときの思い出
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
 
イミュータブルデータモデルの極意
イミュータブルデータモデルの極意イミュータブルデータモデルの極意
イミュータブルデータモデルの極意
 
イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
もしOracleDBAがMySQLを管理することになったときの注意点など
もしOracleDBAがMySQLを管理することになったときの注意点などもしOracleDBAがMySQLを管理することになったときの注意点など
もしOracleDBAがMySQLを管理することになったときの注意点など
 
InnoDBのすゝめ(仮)
InnoDBのすゝめ(仮)InnoDBのすゝめ(仮)
InnoDBのすゝめ(仮)
 
初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!初心者向けMongoDBのキホン!
初心者向けMongoDBのキホン!
 
jooqってなんて読むの? から始めるO/RマッパーとSpringBootの世界
jooqってなんて読むの? から始めるO/RマッパーとSpringBootの世界jooqってなんて読むの? から始めるO/RマッパーとSpringBootの世界
jooqってなんて読むの? から始めるO/RマッパーとSpringBootの世界
 
Redisの特徴と活用方法について
Redisの特徴と活用方法についてRedisの特徴と活用方法について
Redisの特徴と活用方法について
 
Hadoopの概念と基本的知識
Hadoopの概念と基本的知識Hadoopの概念と基本的知識
Hadoopの概念と基本的知識
 
さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)さいきんの InnoDB Adaptive Flushing (仮)
さいきんの InnoDB Adaptive Flushing (仮)
 
TLS, HTTP/2演習
TLS, HTTP/2演習TLS, HTTP/2演習
TLS, HTTP/2演習
 
マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜マルチテナントのアプリケーション実装〜実践編〜
マルチテナントのアプリケーション実装〜実践編〜
 
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
Spring Boot の Web アプリケーションを Docker に載せて AWS ECS で動かしている話
 
binary log と 2PC と Group Commit
binary log と 2PC と Group Commitbinary log と 2PC と Group Commit
binary log と 2PC と Group Commit
 

Viewers also liked

Viewers also liked (18)

LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境
LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境
LastaFluteに移行したFessとElasticsearch+ESFluteによるDBFlute環境
 
Elasticsearchベースの全文検索システムFess
Elasticsearchベースの全文検索システムFessElasticsearchベースの全文検索システムFess
Elasticsearchベースの全文検索システムFess
 
A Tour of npm-resource
A Tour of npm-resourceA Tour of npm-resource
A Tour of npm-resource
 
ElasticsearchとTasteプラグインで作るレコメンドシステム
ElasticsearchとTasteプラグインで作るレコメンドシステムElasticsearchとTasteプラグインで作るレコメンドシステム
ElasticsearchとTasteプラグインで作るレコメンドシステム
 
Tensor Decomposition and its Applications
Tensor Decomposition and its ApplicationsTensor Decomposition and its Applications
Tensor Decomposition and its Applications
 
PredictionIOでSparkMLを使った開発方法
PredictionIOでSparkMLを使った開発方法PredictionIOでSparkMLを使った開発方法
PredictionIOでSparkMLを使った開発方法
 
Elasticsearchで作る形態素解析サーバ
Elasticsearchで作る形態素解析サーバElasticsearchで作る形態素解析サーバ
Elasticsearchで作る形態素解析サーバ
 
Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方Elasticsearchプラグインの作り方
Elasticsearchプラグインの作り方
 
AI社会論研究会
AI社会論研究会AI社会論研究会
AI社会論研究会
 
Scala警察のすすめ
Scala警察のすすめScala警察のすすめ
Scala警察のすすめ
 
[DL輪読会]A Bayesian Perspective on Generalization and Stochastic Gradient Descent
 [DL輪読会]A Bayesian Perspective on Generalization and Stochastic Gradient Descent [DL輪読会]A Bayesian Perspective on Generalization and Stochastic Gradient Descent
[DL輪読会]A Bayesian Perspective on Generalization and Stochastic Gradient Descent
 
全文検索サーバ Fess 〜 全文検索システム構築時の悩みどころ
全文検索サーバ Fess 〜 全文検索システム構築時の悩みどころ全文検索サーバ Fess 〜 全文検索システム構築時の悩みどころ
全文検索サーバ Fess 〜 全文検索システム構築時の悩みどころ
 
TensorFlowで逆強化学習
TensorFlowで逆強化学習TensorFlowで逆強化学習
TensorFlowで逆強化学習
 
失敗と向き合う姿勢を正す話
失敗と向き合う姿勢を正す話失敗と向き合う姿勢を正す話
失敗と向き合う姿勢を正す話
 
生成モデルの Deep Learning
生成モデルの Deep Learning生成モデルの Deep Learning
生成モデルの Deep Learning
 
高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!高速なソートアルゴリズムを書こう!!
高速なソートアルゴリズムを書こう!!
 
TectonicはKubernetesの構築・管理基盤である -概要の章-/-構築の章-
TectonicはKubernetesの構築・管理基盤である -概要の章-/-構築の章-TectonicはKubernetesの構築・管理基盤である -概要の章-/-構築の章-
TectonicはKubernetesの構築・管理基盤である -概要の章-/-構築の章-
 
サーバサイド Kotlin
サーバサイド Kotlinサーバサイド Kotlin
サーバサイド Kotlin
 

Similar to ESFluteによるElasticsearchでのO/Rマッパーを用いた開発

ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
Takayuki Shimizukawa
 
掲示板時間軸コーパスを用いたワードトレンド解析(公開版)
掲示板時間軸コーパスを用いたワードトレンド解析(公開版)掲示板時間軸コーパスを用いたワードトレンド解析(公開版)
掲示板時間軸コーパスを用いたワードトレンド解析(公開版)
moai kids
 
Cmsインサイド 120801 公開版
Cmsインサイド 120801 公開版Cmsインサイド 120801 公開版
Cmsインサイド 120801 公開版
株式会社RYUS
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
Naoyuki Yamada
 

Similar to ESFluteによるElasticsearchでのO/Rマッパーを用いた開発 (20)

Fess/Elasticsearchを使った業務で使える?全文検索への道
Fess/Elasticsearchを使った業務で使える?全文検索への道Fess/Elasticsearchを使った業務で使える?全文検索への道
Fess/Elasticsearchを使った業務で使える?全文検索への道
 
Mongo db使ってみよう
Mongo db使ってみようMongo db使ってみよう
Mongo db使ってみよう
 
[Japan Tech summit 2017] DAL 005
[Japan Tech summit 2017] DAL 005[Japan Tech summit 2017] DAL 005
[Japan Tech summit 2017] DAL 005
 
Tuning maniax 2014 Hadoop編
Tuning maniax 2014 Hadoop編Tuning maniax 2014 Hadoop編
Tuning maniax 2014 Hadoop編
 
ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
ドキュメンテーションを加速するストレスフリーの作図ツール『blockdiag』 jus2011年6月勉強会
 
掲示板時間軸コーパスを用いたワードトレンド解析(公開版)
掲示板時間軸コーパスを用いたワードトレンド解析(公開版)掲示板時間軸コーパスを用いたワードトレンド解析(公開版)
掲示板時間軸コーパスを用いたワードトレンド解析(公開版)
 
はじめての Azure 開発
はじめての Azure 開発はじめての Azure 開発
はじめての Azure 開発
 
Cmsインサイド 120801 公開版
Cmsインサイド 120801 公開版Cmsインサイド 120801 公開版
Cmsインサイド 120801 公開版
 
Integrating elasticsearch with asp dot net core
Integrating elasticsearch with asp dot net coreIntegrating elasticsearch with asp dot net core
Integrating elasticsearch with asp dot net core
 
データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回データマイニング+WEB勉強会資料第6回
データマイニング+WEB勉強会資料第6回
 
エンジニアのための Azure 基礎知識
エンジニアのための Azure 基礎知識エンジニアのための Azure 基礎知識
エンジニアのための Azure 基礎知識
 
DBFluteを用いて開発されている全文検索システムFess
DBFluteを用いて開発されている全文検索システムFessDBFluteを用いて開発されている全文検索システムFess
DBFluteを用いて開発されている全文検索システムFess
 
PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門PHP開発者のためのNoSQL入門
PHP開発者のためのNoSQL入門
 
[db tech showcase Tokyo 2016] A13: 最新版VerticaのAnalytics機能を駆使して実現する簡単ログ分析 by日本...
[db tech showcase Tokyo 2016] A13: 最新版VerticaのAnalytics機能を駆使して実現する簡単ログ分析 by日本...[db tech showcase Tokyo 2016] A13: 最新版VerticaのAnalytics機能を駆使して実現する簡単ログ分析 by日本...
[db tech showcase Tokyo 2016] A13: 最新版VerticaのAnalytics機能を駆使して実現する簡単ログ分析 by日本...
 
HTML5&API総まくり
HTML5&API総まくりHTML5&API総まくり
HTML5&API総まくり
 
CRF を使った Web 本文抽出 for WebDB Forum 2011
CRF を使った Web 本文抽出 for WebDB Forum 2011CRF を使った Web 本文抽出 for WebDB Forum 2011
CRF を使った Web 本文抽出 for WebDB Forum 2011
 
Azure Machine Leaning Workbench の使い方
Azure Machine Leaning Workbench の使い方Azure Machine Leaning Workbench の使い方
Azure Machine Leaning Workbench の使い方
 
Designing Interfaces Book Reading #3: Chapter 5
Designing Interfaces Book Reading #3: Chapter 5Designing Interfaces Book Reading #3: Chapter 5
Designing Interfaces Book Reading #3: Chapter 5
 
Azure Cosmos DB を使った クラウドネイティブアプリケーションの 設計パターン
Azure Cosmos DB を使った クラウドネイティブアプリケーションの 設計パターンAzure Cosmos DB を使った クラウドネイティブアプリケーションの 設計パターン
Azure Cosmos DB を使った クラウドネイティブアプリケーションの 設計パターン
 
Mongodb
MongodbMongodb
Mongodb
 

More from Shinsuke Sugaya

Solrベースの全文検索サーバ Fess
Solrベースの全文検索サーバ FessSolrベースの全文検索サーバ Fess
Solrベースの全文検索サーバ Fess
Shinsuke Sugaya
 

More from Shinsuke Sugaya (11)

社内ドキュメント検索システム構築のノウハウ
社内ドキュメント検索システム構築のノウハウ社内ドキュメント検索システム構築のノウハウ
社内ドキュメント検索システム構築のノウハウ
 
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようLastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめよう
 
PredictionIOのPython対応計画
PredictionIOのPython対応計画PredictionIOのPython対応計画
PredictionIOのPython対応計画
 
PredictionIO構築入門
PredictionIO構築入門PredictionIO構築入門
PredictionIO構築入門
 
SolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみようSolrとElasticsearchを比べてみよう
SolrとElasticsearchを比べてみよう
 
Elasticsearch Authプラグインでアクセスコントロール
Elasticsearch AuthプラグインでアクセスコントロールElasticsearch Authプラグインでアクセスコントロール
Elasticsearch Authプラグインでアクセスコントロール
 
DBFlute Mavenプラグインを用いてCRUD作成
DBFlute Mavenプラグインを用いてCRUD作成DBFlute Mavenプラグインを用いてCRUD作成
DBFlute Mavenプラグインを用いてCRUD作成
 
elasticsearchプラグイン入門
elasticsearchプラグイン入門elasticsearchプラグイン入門
elasticsearchプラグイン入門
 
Solrベースの全文検索サーバ Fess
Solrベースの全文検索サーバ FessSolrベースの全文検索サーバ Fess
Solrベースの全文検索サーバ Fess
 
Sc2009autumn s2robot
Sc2009autumn s2robotSc2009autumn s2robot
Sc2009autumn s2robot
 
オフィスに1台!全文検索Fess
オフィスに1台!全文検索Fessオフィスに1台!全文検索Fess
オフィスに1台!全文検索Fess
 

ESFluteによるElasticsearchでのO/Rマッパーを用いた開発