elasticsearch6 dsl解析(1)

版本号:6.0.1

上两周,es从2升级到6,而我负责升级的东西,只有查询,写dsl写的快吐了,在这里吐槽下,mysql导入es的字段原汁原味的,字段都不转化的。如下图
在这里插入图片描述

mmp,然后只能自己做了字段转换,言归正传,写了那么多dsl,在想底层怎么解析,一直没时间,趁着元旦写一下,底层是lucene,从lucene先看起来,es6.0.1采用lucene的版本7.0.1,下载代码导入idea,这个可以谷歌。

Query中rewrite是重新构建语法数的方法,Query子类如下图

在这里插入图片描述

类没截全,太多了,其中MultiTermQuery( 抽象类)和BooleanQuery是常用的,MultiTermQuery子类如下

在这里插入图片描述

比如类似下面常遇到的查询

{

"query": {

    "bool": {

        "must": [

            { "term": { "title": "Search" }},

           { "wildcard": { "content": "Elasticsearch*“}}

        ],

        "filter": [

            { "term": { "status": "published" }},

            { "range": { "publish_date": { "gte": "2019­01­01" }}}

        ]

    }

}

}

BooleanQuery.rewrite方法太长,不上图了,其中有一段是这样的
在这里插入图片描述

重写rewrite方法,所以问题回到了只看常用的MultiTermQuery类,其它的暂时不解析,类太多了。MultiTermQuery提供了三种Query树重写的方法,第一种是CONSTANT_SCORE_REWRITE,第二种SCORING_BOOLEAN_REWRITE,第三种CONSTANT_SCORE_BOOLEAN_REWRITE。

第一种使得MultiTermQuery对应的大于16个的Term看成一个Term(小于16个的term转换成BooleanQuery and形式),组成一个docid set,作为统一的倒排表参与倒排表的合并,这样无论这样的Term在索引中有多少,都只会有一个倒排表参与合并,不会产生TooManyClauses异常,也使得性能得到提高。但是多个Term之间的tf, idf等差别将被忽略.

第二种使得整个Query对象树被展开,叶子节点都为TermQuery,MultiTermQuery中的多个Term可根据在索引中的tf, idf等参与打分计算(和第三种方式的区别在于第三种方式分数是个常量),然而我们事先并不知道索引中和MultiTermQuery相对应的Term到底有多少个,因而会出现TooManyClauses异常,也即一个BooleanQuery中的子查询太多。这样会造成要合并的倒排表非常多,从而影响性能。

我们常用的是第一种方式我们只是需要模糊搜索不需要打分,所以只分析第一种,第一种打分方式是在MultiTermQueryConstantScoreWrapper.rewrite

放个demo,如下

Directory dir1 =newDirectory();

RandomIndexWriter iw1 =new RandomIndexWriter(random(), dir1);

Document doc1 =new Document();

doc1.add(newTextField(“field”, “foo bar”, Field.Store.NO));

iw1.addDocument(doc1);

IndexReader reader1 = iw1.getReader();

iw1.close();

Directory dir2 =newDirectory();

RandomIndexWriter iw2 =new RandomIndexWriter(random(), dir2);

Document doc2 =new Document();

doc2.add(newTextField(“field”, “foo baz”, Field.Store.NO));

iw2.addDocument(doc2);

IndexReader reader2 = iw2.getReader();

iw2.close();

BooleanQuery.Builder query =new BooleanQuery.Builder(); // Query: +foo -ba*

query.add(new TermQuery(new Term(“field”, “foo”)), BooleanClause.Occur.MUST);

WildcardQuery wildcardQuery =new WildcardQuery(new Term(“field”, “ba*”));

// wildcardQuery.setRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_REWRITE);

wildcardQuery.setRewriteMethod(MultiTermQuery.CONSTANT_SCORE_REWRITE);

query.add(wildcardQuery, BooleanClause.Occur.MUST_NOT);

MultiReader multireader =new MultiReader(reader1, reader2);

IndexSearcher searcher =newSearcher(multireader);

assertEquals(0, searcher.search(query.build(), 10).totalHits);

es.awaitTermination(1, TimeUnit.SECONDS);

multireader.close();

reader1.close();

reader2.close();

dir1.close();

dir2.close();

刚开始Query如图
在这里插入图片描述

执行foo没有变化,当执行到ba*的时候截图如下

在这里插入图片描述
在这里插入图片描述
会把*自动补全,然后转换成一个一个的term然后去取数据,至于如何取数据和补数据,后面再说,太复杂了,这只是其中很少的一小块,还有很长的路要走。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值