ElasticSearch关键技术

本部分主要是ElasticSearch相关技术整理,但是ElasticSearch的特点就是API更新非常快,导致书籍/博客很难有最快的跟进,本部分主要讲解部分不随大版本更新的技术。

ElasticSearch可以用来作为数据库吗

Elastic网上很少有作为基础数据库的案例,主要是它的聚合过滤等能力(相对于Oracle/MongoDb)实在太弱,但是它的优点是写入方便(动态模版等功能),扩展方便。在本章节中,本文主要是将ElasticSearch作为数据仓库(Data Warehouse),最原始的数据库肯定是存储在传统数据库中,而Elastic仅仅用于存储ETL/Flink等离线或实时聚合操作后的计算结果。

graph LR;
	subgraph Source
    HTML--Puppeteer-->Kafka;
    Excel/Word--Tika-->Kafka;
    Oracle-->Kafka;
    end
    Kafka--ETL-->Flink;
    Flink-->ElasticSearch;

在上图中,Elastic虽然是数据库,但是不会保留任何原始数据

本部分实验条件

本部分只分析单机版,并安装IK分词

# install ik plugin
./bin/elasticsearch-plugin install \
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.5.4/elasticsearch-analysis-ik-6.5.4.zip
# start
./bin/elasticsearch -d

本文的模拟数据采用Kibana自带的Demo数据,启动Kibana就会提示自动导入

Explain

调试是掌握任何框架的第一步,在Elastic中通过Explain调试为什么某个字段的分数那么高

测试数据,我们采用Demo数据中的SKU作为参数,它是keyword类型

GET kibana_sample_data_ecommerce/_search?explain=true
{
  "_source": ["sku"], 
  "query": {
    "term": {
      "sku": "ZO0450004500"
    }
  }
}

返回的Explain

-- -- 7.5339074
weight(sku:ZO0450004500 in 55) [PerFieldSimilarity], result of:
	-- -- 7.5339074
	score(doc=55,freq=1.0 = termFreq=1.0\n), product of:
		-- 7.5339074
		idf, computed as log(1 + (docCount - docFreq + 0.5) / (docFreq + 0.5)) from:
			-- 2.0(kibana_sample_data_ecommerce中符合条件的个数)
			docFreq
			-- 4675.0(kibana_sample_data_ecommerce的总个数)
			docCount
		-- 1.0
      	tfNorm, computed as (freq * (k1 + 1)) / (freq + k1) from:
      		-- 1.0
      		termFreq=1.0
      		-- 1.2
      		parameter k1(1.2)
      		-- 0
			parameter b (norms omitted for field)(0)

精确搜索

在项目中,除了使用它常见的IK分词,还有精确使用场景,比如ETL保存计算结果,缓存nested结构体等功能。比如我的某个项目中,有100多个properties都需要支持检索。如果用传统数据库实现,肯定累死的,这种精确搜索功能需要使用ElasticSearch中的NoSQL功能(ElasticSearch as a NoSQL database)

Keyword类型

Keyword用于搜索精确值(exact-value),它内部不支持分词,直接存储到

分词搜索

分词

StandardTokenizer

在标准分词中,使用JFex生成产生。

org.apache.lucene.analysis.standard.StandardTokenizerImpl

自动补全

从头开始自动补全主要有三种实现

  • 最简单的全文遍历,比如Prefix
  • 基于E-NGram实现
  • 基于类型Completion实现

如果你希望从中间自动补全,那么可以通过如下