Elasticsearch 変わり種プラグインの作り方

34
変変変変変変変変変変 変変変 変変変変

Transcript of Elasticsearch 変わり種プラグインの作り方

変わり種プラグインの作り方

黒澤亮二

自己紹介

• 黒澤亮二 @rjkuro• 日本 IBM• データベース周辺の製品開発• Elasticsearch 暦 6 ヶ月• 最近の興味:

分散データベースNoSQLSearch/Analysis

自己紹介

• 黒澤亮二 @rjkuro• 日本 IBM• データベース周辺の製品開発• Elasticsearch 暦 6 ヶ月• 最近の興味:

分散データベースNoSQLSearch/Analysis

自己紹介

• 黒澤亮二• 日本 IBM• データベース周辺のソフト開発• Elasticsearch 暦 6 ヶ月• 最近の興味:分散 DB, NoSQL, 検索

disclaimer

• 嘘知識を聴く可能性があります• 聞き間違いだと思ってください• 資料は後からこっそり直す可能性があります

• 本資料は私自身の見解であり、必ずしも私の所属する組織の立場、戦略、意見を代表するものではありません。

本日の主張

つくれるよいろんなプラグイン

Elasticsearch はプラグインで機能を追加できる

既存のたくさんあるし

簡単につくれるよ

maven

bin/plugin --install myplugin --url file:///test/myplugin.zip

pom.xmles-plugin.propertiesplugin.xmlMyPlugin.javaMyModule.java

myplugin.zip

プラグイン作れるといいことあるよ

アプリ Elasticsearch

アプリでの処理を…

プラグイン作れるといいことあるよ

アプリ Elasticsearch

Elasticsearch ノードで動かせる!!

スケールする!

アプリ Elasticsearch Elasticsearch

Elasticsearch Elasticsearch

スケールする!!

アプリ Elastic Elastic Elastic

Elastic Elastic Elastic

Elastic Elastic Elastic

スケールする!!!

アプリ

いろいろできるよ

モジュールで「登録メソッド」をよんで新機能を差しこめる!

River プラグインはこれ

Analyzer プラグインはこれ

https://www.found.no/foundation/elasticsearch-internals/

登録メソッドたくさん!AnalysisModule.addTokenizer(String name, Class<? extends TokenizerFactory> tokenizer)AnalysisModule.addTokenFilter(String name, Class<? extends TokenFilterFactory> tokenFilter)AnalysisModule.addCharFilter(String name, Class<? extends CharFilterFactory> charFilter)AnalysisModule.addAnalyzer(String name, Class<? extends AnalyzerProvider> analyzer)RestController.registerHandler(RestRequest.Method method, String path, RestHandler handler)RestModule.addRestAction(Class<? extends BaseRestHandler> restAction)DocumentMapperParser.putTypeParser(String type, Mapper.TypeParser typeParser)HighlightModule.registerHighlighter(Class<? extends Highlighter> clazz)IndicesLifecycle.addListener(Listener listener)IndexQueryParserModule.addQueryParser(String name, Class<? extends QueryParser> queryParser)

プラグイン専用ではなくElasticsearch 本体も使ってます

プラグインから登録メソッドどうやって呼ぶか?

1. es-plugin.properties に自分の Plugin クラス名を書く

2. Plugin クラスで自分の Module クラスを登録 (onModule があればここで登録メソッドを呼べる場合も )

3. 自分の Module クラスの configure()に自分のコンポーネントの生成方法を指定

4. コンポーネントのクラスのコンストラクタに @injection をつける

5. コンストラクタの引数にほしいものを書く

6. 受け取ったものを使って登録メソッドを呼ぶ

1. es-plugin.properties に自分の Plugin クラス名を書く

2. Plugin クラスで自分の Module クラスを登録 (onModule があればここで登録メソッドを呼べる場合も )

3. 自分の Module クラスの configure()に自分のコンポーネントの生成方法を指定

4. コンポーネントのクラスのコンストラクタに @injection をつける

5. コンストラクタの引数にほしいものを書く

6. 受け取ったものを使って登録メソッドを呼ぶ

→  例で

例 Mapper プラグイン

Mapper モジュール

plugin=myplugin.MyPlugin

public class MyPlugin extends AbstractPlugin {

  public Collection<Class<? extends Module>> indexModules() { Collection<Class<? extends Module>>

modules = Lists.newArrayList(); modules.add(MyMapperModule.class); return modules; } … …

私のプラグインのクラス名

私のモジュールを登録

es-plugin.properties

public class MyMapperModule extends AbstractModule { @Override protected void configure() { bind(MyMapperComponent.class).asEagerSingleton(); }}

public class MyMapperComponent extends AbstractIndexComponent {

@Inject public MyMapperComponent(Index index,

@IndexSettings Settings indexSettings, MapperService mapperService) {

super(index, indexSettings);

mapperService.documentMapperParser() .putTypeParser("my_type",

new MyMapper.TypeParser()); }}

「私のクラスを起動時に生成してよー」

欲しいものを渡してもらっ

登録メソッドが呼べた

ここで Guice のおまじないをすると…

使いみちは、Index 時の事前処理とかPUT /test/person/1{ "my_content" : "... 長い文章 ..."}

{ “content” : “... 処理済の文章 ...",}

解析処理をしてフィールド追加とかできる!PUT /test/person/1{ "my_content" : "... 長い文章 ..."}

{ "content" : "... 長い文章 ...", "language" : "ja", "classification" : "essay", "sentiment" : "positive", "advertised_products" : { ... } …}

なにか既視感?

元ネタはattachment プラグイン

PUT /test/person/1{ "my_attachment" : "... base64 ..."}

{ "my_attachment.title" : ".…", "my_attachment.date" : "...", "my_attachment.author" : "….", "my_attachment.keywords" : "…", "my_attachment.content_type" : "…", " …}

というわけで詳しくは:https://github.com/elastic/elasticsearch-mapper-attachments

例2: Custom query parser

Query モジュール

使いみち

• Match クエリ /Query String クエリでは物足りない場合• スコアを細かく制御したい場合• インデックスに特殊な構造を持たせてそれを

検索に利用したい場合

→  自前のシンタックスを実装したりLucene の Query 自体をカスタムして利用できる

登録メソッドを持ったオブジェクトが渡されてくる楽なパターンpublic class MyPlugin extends AbstractPlugin {

public void onModule(IndexQueryParserModule module) { module.addQueryParser("my_query",

MyQueryParser.class); } … …

登録メソッドここで呼べちゃう

public class MyQueryParser implements QueryParser {

public Query parse(QueryParseContext parseContext) throws IOException,   QueryParsingException {

XContentParser parser = parseContext.parser(); Token curToken = parser.currentToken();

…… トークンをパースして Query を返す処理 ……

Lucene のオブジェクトを返

せる

例その3: Lifecycle イベント処理

Indices モジュールIndicesLifecycle インターフェー

イベントをフックして処理を挿入できる!- インデックスやシャード

の open/close の前後- シャード移動の前後など

public class MyLifeCycleModule extends AbstractModule { @Override protected void configure() { bind(MyLifeCycleComponent.class).asEagerSingleton(); }}

「私のクラスを(ry 」

public class MyLifecycleComponent extends AbstractComponent { @Inject public MyLifecycleComponent(Settings settings, IndicesLifecycle indicesLifecycle) { super(settings); indicesLifecycle.addListener(

new IndicesLifecycle.Listener() { @Override public void

    afterIndexCreated(IndexService indexService) { … index が open されたときの処理 … }

登録メソッド

まとめ

• プラグインは使うだけじゃない• いろいろ作れる• スケールさせやすい• Guice が欲しいオブジェクトを渡してくれる• ストアドプロシージャー的な使い方もありか

参考資料

プラグイン一般 https://www.found.no/foundation/elasticsearch-internals/ https://www.found.no/foundation/writing-a-plugin/Attachment mapper pluginhttps://github.com/elastic/elasticsearch-mapper-attachmentsElasticsearch reference https://www.elastic.co/guide/en/elasticsearch/reference/1.5/index.html