Contenu connexe Similaire à Elasticsearch 20150107 Similaire à Elasticsearch 20150107 (20) Elasticsearch 201501074. 自己紹介
• 大川 真吾
GitHub @shingoOKAWA
Twitter @okawa_shingo
• Supership株式会社 インフラ事業開発本部検索グループ エンジニア
2015年11月入社
• バックエンドエンジニア (Elasticsearch歴 3ヶ月目 池田さん感謝)
検索エンジン関連バックエンド設計/実装全般
• 静岡出身、加速器工学専攻 (物理シミュレーションとか)
• プログラミング好き
4
9. Query Parser 実装してみた
• こんな Query Parser 実装してみた
⑴クエリテキストレベルで近接検索(Proximity Search) や 分離検索(DisMax) 対応
⑵文法の違いをクエリテキストレベルで隠蔽
⑶簡素な BNF で DSQ(Domain Specific Query) を簡単に実装可能
⑷構文木 (Concrete/Abstract Syntax Tree) 周りの API 対応
9
検索プラットフォームの実現
10. Query Parser 実装してみた
• 何が嬉しいの?
⑴距離などを考慮したより詳細な検索実現
⑵検索プラットフォーム実現によりプロダクト・サービスの多様化、統合対応
⑶小さなコストで種々の検索UX改善サイクルを回せる
⑷トークンの揺らぎ(同義語など)等を、プログラマブルに構文木レベルで対応
10
11. Query Parser 実装してみた
1. 近接検索
PhraseQuery や SpanQuery (後述)
Term 間の距離を検索条件として付加できる
11
PhraseQuery: “cat dog bird”, slop: 3 SpanQuery: “cat dog” bird, slop: 3
cat birdhorse lizard dog
2 0
cat birdhorse lizarddog
20
13. Query Parser 実装してみた
3. 直感的で分かりやすい ANTLR BNF
既存実装 QueryParser.jj と比較して直感的で分かりやすい
13
Query Query(String field) :
{
Query q, firstQuery=null;
int conj, mods;
}
{
mods=Modifiers() q=Clause(field)
{
addClause(clauses, CONJ_NONE, mods, q);
if (mods == MOD_NONE) firstQuery=q;
}
:
:
grammar ExternalQuery;
import CommonLexerRules;
query : (expression)+
;
expression : CONJUNCTION_AND clause
| CONJUNCTION_OR clause
| clause
;
:
:
:
14. Query Parser 実装してみた
4. 構文木 API
Concrete Syntax Tree や Abstract Syntax Tree を用いて解析フェーズを多段階に
品詞による Term 結合や Synonym 等の揺らぎをよりフレキシブルに対応可能
14Concrete Syntax Tree
OR
FF ドラクエ
Abstract Syntax Tree
BooleanClause
AT SAME POSITION
FF Final Fantasy ファイファン
TAG: BOOLEAN
TAG: TERM TAG: TERM
16. Lucene おさらい
• Apache Lucene IR Library
⑴Language Analysis (Filtering, Normalize, Tokenize…)
⑵Indexing and Storage (Lock-Free Indexing, Near-Real-Time Indexing…)
⑶Querying (50-over Query Implemantations, Parser, Scoring Model…)
16
Querying 機能を積極的に使って”検索”プラットフォーム
としてElasticsearchのQueryDSLを最大限利用
17. Lucene おさらい
17
Document
- field1
- field2
Text Analysis Chains
IndexWriter
DocumentWriter
Indexing Chain
QueryParser Query String
IndexReader
ScorerQuery
Indexing Chain Segment
Persistent Layer
SegmentReader
TermsEnum
PositionsEnum
19. Lucene クエリと近接検索
• Apache Lucene Query API
⑴基本的なクエリ (TermQuery, BooleanQuery…)
⑵曖昧検索系のクエリ (WildcardQuery, RegexpQuery…)
⑶近接検索系のクエリ (SpanQuery, PhraseQuery…)
19
20. Lucene クエリと近接検索
• Apache Lucene Query API
⑴基本的なクエリ (TermQuery, BooleanQuery…)
⑵曖昧検索系のクエリ (WildcardQuery, RegexpQuery…)
⑶近接検索系のクエリ (SpanQuery, PhraseQuery…)
20
• ユーザーの検索文字列から如何に意図を汲み取るかが重要
• ユーザーはトークナイズのロジックなど知る由も無い
• 品詞情報や同義語辞書、Term間距離等サービス側で考慮
21. Lucene クエリと近接検索
1. PhraseQuery
Term 間の距離を検索条件として付加できる
Search Phaseで Analyzer によるトークナイズが適用される
21
“cat dog bird”, slop: 3
cat birdhorse lizard dog
2 0
21
Matched Document
PhraseQuery
cat
TermQuery TermQuery TermQuery
dog bird
22. Lucene クエリと近接検索
2. SpanNearQuery
SpanTerm 間の距離、その順序を検索条件として付加できる
Search Phaseで Analyzer によるトークナイズが適用されない
22
“cat dog” bird, slop: 3
22
Matched Document
SpanNearQuery
cat
SpanTerm
Query
dog bird
SpanTerm
Query
SpanTerm
Query
cat birdhorse lizarddog
20
25. Domain Specific Query
1. 外部 (実サービス向け) クエリ
2. 内部 (開発者向け) クエリ
3. 距離検索クエリ
25
{
"query": {
"hetero_query": {
"query": "this AND that",
"handler_name": "external_mapper”
}
}
}
{
"query": {
"hetero_query": {
"query": "this AND that",
"handler_name": ”internal_mapper”
}
}
}
26. Domain Specific Query
26
grammar ExternalQuery;
import CommonLexerRules;
query : (expression)+
;
expression : CONJUNCTION_AND clause
| CONJUNCTION_OR clause
| clause
;
clause : MODIFIER_REQUIRE field
| MODIFIER_NEGATE field
| field
;
field : {_input.LT(2).getType() == COLON}? SINGLE_LITERAL COLON term
| term
;
term : SINGLE_LITERAL # BareTerm | PHRASE_LITERAL # QuotedTerm ;
27. Domain Specific Query
27
grammar InternalQuery;
import CommonLexerRules;
query : (expression)+
;
expression : CONJUNCTION_AND clause
| CONJUNCTION_DIS clause
| CONJUNCTION_OR clause
| LPAREN query RPAREN
| clause
;
clause : MODIFIER_REQUIRE field (HAT SINGLE_LITERAL)?
| MODIFIER_NEGATE field (HAT SINGLE_LITERAL)?
| field (HAT SINGLE_LITERAL)?
;
field : {_input.LT(2).getType() == COLON}? SINGLE_LITERAL COLON term
| term
;
term : SINGLE_LITERAL # BareTerm | PHRASE_LITERAL # QuotedTerm ;
29. 今後の予定
1. クエリ文法の充実 (Google等価等)
2. Synonym Map の AST API を用いた実装
3. 品詞による Term 結合の AST API を用いた実装
4. Span系クエリ文法の精査
5. ドキュメント作成
その他 Query Parser 以外にも順次コア機能を開発予定
公開可能なものは弊社リポジトリで公開
29