1、题记

2018年3月初,萌生了一个想法:对Elasticsearch相关的技术书籍做拆解阅读,该想法源自非计算机领域红火已久的【樊登读书会】、得到的每天听本书、XX拆书帮等。

目前市面上Elasticsearch的中文书籍就那么基本,针对ES5.X以上的三本左右;国外翻译有几本,都是针对ES1.X,2.X版本,其中《深入理解Elasticsearch》还算比较经典。

拆书的目的:

  • 1)梳理已有的Elasticsearch知识体系;
  • 2)拾遗拉在角落的Elasticsearch知识点;
  • 3)通过手敲动代码或命令行,在实践中再次“温故知新”,提前增加知识储备,避免项目/产品实战中的“临阵抱佛脚”;
  • 4)最大化的节省您的宝贵时间,让您最快的时间吸取最精华的“干货”。

本次解读是《从Lucene到Elasticsearch全文检索实战》。

2、本书梗概

作者是中科院硕士姚攀(90后)在读研究生期间根据实习写成CSDN博客,最终成书。

  • 该书1/4章节讲解Lucence相关原理及实战;
  • 1/2章节讲解Elasticsearch基本概念:集群入门、搜索分类详解、聚合分析、Java API;
  • 1/4章节讲解Elasticsearch集群管理、项目实战、Hadoop实战。

总体评价:

优点:

  • 1)涵盖了Elasticsearch相关的基本概念、基础原理;
  • 2)有两个实战项目分享;

缺点:

  • 1)某些概念就只是有分类,没有讲解出不同分类的区别,不同分类的适用场景;
  • 2)某些细节点涵盖不全,偏理论,好多知识技术点,实战中应用会有不同。
  • 3)书基于Elasticsearch5.4.0讲解,一些特性6.X已不适用。

3、核心知识点梳理

以下的DSL都是通过ElasticsearchV6.2.2版本试验过的。

3.1 mget 一次获取多个文档。

1GET test_index/test_type/_mget
2{
3 "docs":[
4 {"_id":1},
5 {"_id":3}
6 ]
7}

最小简化版本:

1GET test_index/test_type/_mget
2{
3 "ids":[1,3]
4}

3.2 update更新

——添加、删除、更新字段

1POST test_index/test_type/1
2{
3 "no":1,
4 "name":"奔驰X100",
5 "addr":"德国",
6 "price":1000000,
7 "tags" : ["red"]
8}

3.2.1 添加字段

以下添加了新字段tags,赋值为“red”。

1POST test_index/test_type/1/_update
2{
3 "script":"ctx._source.tags = \"red\""
4}

修改后结果为:

1{
2 "_index": "test_index",
3 "_type": "test_type",
4 "_id": "1",
5 "_version": 6,
6 "found": true,
7 "_source": {
8 "no": 1,
9 "name": "奔驰X100",
10 "addr": "德国",
11 "price": 1000000,
12 "tags": "red"
13 }
14}

3.2.2 删除字段

1POST test_index/test_type/1/_update
2{
3 "script":"ctx._source.remove(\"new_field\")"
4}

3.2.3 更新字段-添加

 1POST test_index/test_type/1/_update
2{
3 "script" : {
4 "source": "ctx._source.tags.add(params.tag)",
5 "lang": "painless",
6 "params" : {
7 "tag" : "blue"
8 }
9 }
10}

更新后结果如下:

1{
2 "_index": "test_index",
3 "_type": "test_type",
4 "_id": "1",
5 "_version": 8,
6 "found": true,
7 "_source": {
8 "no": 1,
9 "name": "奔驰X100",
10 "addr": "德国",
11 "price": 1000000,
12 "tags": [
13 "red",
14 "blue"
15 ]
16 }
17}

3.2.4 删除字段(if判定)

 1POST test_index/test_type/1/_update
2{
3 "script" : {
4 "source": "if (ctx._source.tags.contains(params.tag)) { ctx.op = 'delete' } else { ctx.op = 'none' }",
5 "lang": "painless",
6 "params" : {
7 "tag" : "red"
8 }
9 }
10}

3.3 bulk批量请求的注意事项

  1. 每一行的结尾处都必须有换行符"\n",最后一行也要有,换行符可以有效的分隔每行。
  2. 注意一次提交文件的大小,整个批量请求需要被加载到请求节点的内存里,所以请求越大,给其他请求可用的内存越小。
  3. 最佳bulk请求的大小,完全取决于服务器的硬件、文档的大小和复杂度以及索引和搜索的负载。

3.4 并发修改文档导致版本冲突的问题

以下是社区的问题,我认为更切合知识点。

线上的场景可能会对一个文档同一秒进行并发修改,导致会出现个别的VersionConflictEngineException 异常,我猜测是并发upsert请求 可能存在先获取到版本号的请求 比 后获取到版本号的请求 执行慢或者执行晚导致的,

毕竟默认es不会对文档操作加锁。但是如在不做锁机制的情况下处理这个问题呢。

解决方案(初步):

es版本控制有内部和外部两种类型。默认情况下,es使用内部版本控制。

version_type=external的时候是外部值控制。在使用外部版本类型时,

系统会检查传递给索引请求的版本号是否大于当前存储的文档的版本,

如果为true,则文档将被索引并使用新的版本号。

如果提供的值小于或等于存储文档的版本号,则会发生版本冲突,索引操作将失败。

1PUT /test_index/test_type/10?version=1520834740000&version_type=external
2{
3 "newadd":11,
4 "test":"true"
5}

返回结果:

 1{
2 "_index": "test_index",
3 "_type": "test_type",
4 "_id": "10",
5 "_version": 1520834740000,
6 "found": true,
7 "_source": {
8 "newadd": 11,
9 "test": "true"
10 }
11}

所以最简单的实现方式就是每次更新使用当前时间戳作为版本号,

3.5 动态映射和静态映射的区分

  1. 动态映射:文档写入ES中,它会根据字段的类型自动识别,这种称为:动态映射;
  2. 静态映射:写入数据之前对字段的属性进行手工设置。

3.6 text字段的特殊性

  1. 不用于排序,很少用于聚合(termsAggrions除外,未来版本会彻底禁止text类型聚合操作)。

  2. 题外话:如果需要可以借助 multi-fields.使用:keyword 类型。

  3. 官网解读:

    http://t.cn/R6jy9Z3,http://t.cn/RnKU4tG

3.7 数据类型存储建议

对于数字类型的字段,在满足需求的情况下,要尽可能的选择范围小的数字类型。

3.8 过滤和搜索的区别

  1. 过滤:只根据条件对文档进行过滤,不计算评分;
  2. 搜索:解决的是相关度的问题。

当用户输入一个查询,Elasticsearch通过排序模型计算文档和查询关键词之间的相关度,按照评分排序后返回最想关的文档给用户。

e

细化:Elasticsearch接受到关键词以后到倒排索引中进行查询,通过倒排索引中维护的倒排记录表找到关键词对应的文档集合,然后做评分、排序、高亮处理,最终返回搜索结果给用户。

注意:ES是按照查询和文档的相关度进行排序的,默认按照评分降序排序。

3.9指定搜索字段的权重

1GET _search
2{
3 "query":{
4 "multi_match": {
5 "query": "美国",
6 "fields": ["addr^5", "name"]
7 }
8 }
9}

3.10 返回字段中至少有一个非控制的文档。

1GET _search
2{
3 "query":{
4 "exists":{
5 "field":"name"
6 }
7 }
8}

3.11 固定得分检索

 1GET /_search
2{
3 "query": {
4 "constant_score" : {
5 "filter" : {
6 "term" : { "addr.keyword" : "美国"}
7 },
8 "boost" : 1.2
9 }
10 }
11}

返回结果:

1{
2 "took": 1,
3 "timed_out": false,
4 "_shards": {
5 "total": 32,
6 "successful": 32,
7 "skipped": 0,
8 "failed": 0
9 },
10 "hits": {
11 "total": 3,
12 "max_score": 1.2,
13 "hits": [
14 {
15 "_index": "test_index",
16 "_type": "test_type",
17 "_id": "5",
18 "_score": 1.2,
19 "_source": {
20 "no": 5,
21 "name": "福特500",
22 "addr": "美国",
23 "price": 180000
24 }
25 },
26 {
27 "_index": "test_index",
28 "_type": "test_type",
29 "_id": "6",
30 "_score": 1.2,
31 "_source": {
32 "no": 6,
33 "name": null,
34 "addr": "美国",
35 "price": 180000
36 }
37 },
38 {
39 "_index": "test_index",
40 "_type": "test_type",
41 "_id": "3",
42 "_score": 1.2,
43 "_source": {
44 "no": 3,
45 "name": "福特300",
46 "addr": "美国",
47 "price": 300000
48 }
49 }
50 ]
51 }
52}

3.12 修改文档得分检索

借助:function Score Query 实现。

3.13 获取相似文章

1{
2 "query": {
3 "more_like_this": {
4 "fields": [
5 "title"
6 ],
7 "like": "新时代的领路人",
8 "min_term_freq": 1,
9 "max_query_terms": 12
10 }
11 },
12 "_source": "title",
13 "from": 1000,
14 "size": 5
15}

3.14 脚本检索

以下内容是6.X验证的。

5.X版本要把source改成inline。

1POST test_index/_search
2{
3 "query":{
4 "bool":{
5 "must":{
6 "script":{
7 "script":{
8 "source": "doc['price'].value > 100000",
9 "lang":"painless"
10 }
11 }
12 }
13 }
14 }
15}

3.15 多字段高亮

字段高亮已经比较熟悉,有一种场景是:当我搜索title字段的时候,我期望高亮:title、content、abstr如何做到呢?

通俗的讲:

不搜索某个字段,可以顺带高亮该字段。

 1POST test_index/test_type/_search
2{
3 "query":{
4 "match_phrase":{
5 "addr":"美国"
6 }
7 },
8 "highlight": {
9 "require_field_match":false,
10 "fields":{
11 "addr":{"pre_tags":["<strong>"],
12 "post_tags":["</strong>"]
13 },
14 "name":{"pre_tags":["<strong>"],
15 "post_tags":["</strong>"]}
16 }
17 }
18}
1{
2 "took": 116,
3 "timed_out": false,
4 "_shards": {
5 "total": 5,
6 "successful": 5,
7 "skipped": 0,
8 "failed": 0
9 },
10 "hits": {
11 "total": 3,
12 "max_score": 1.1143606,
13 "hits": [
14 {
15 "_index": "test_index",
16 "_type": "test_type",
17 "_id": "6",
18 "_score": 1.1143606,
19 "_source": {
20 "no": 6,
21 "name": "大片美国",
22 "addr": "美国",
23 "price": 180000
24 },
25 "highlight": {
26 "name": [
27 "大片<strong>美</strong><strong>国</strong>"
28 ],
29 "addr": [
30 "<strong>美</strong><strong>国</strong>"
31 ]
32 }
33 },
34 {
35 "_index": "test_index",
36 "_type": "test_type",
37 "_id": "5",
38 "_score": 0.5753642,
39 "_source": {
40 "no": 5,
41 "name": "福特500",
42 "addr": "美国",
43 "price": 180000
44 },
45 "highlight": {
46 "addr": [
47 "<strong>美</strong><strong>国</strong>"
48 ]
49 }
50 },
51 {
52 "_index": "test_index",
53 "_type": "test_type",
54 "_id": "3",
55 "_score": 0.5753642,
56 "_source": {
57 "no": 3,
58 "name": "福特300",
59 "addr": "美国",
60 "price": 300000
61 },
62 "highlight": {
63 "addr": [
64 "<strong>美</strong><strong>国</strong>"
65 ]
66 }
67 }
68 ]
69 }
70}

3.16 分片影响评分

Elasitcsearch 5.4 之后对于text类型的字段,默认采用是BM25评分模型,而不是基于tf-idf的向量空间模型,评分模型的选择可以通过similarity参数在映射中指出。

需要注意的是:ES在每个分片上单独打分,分片的数量会影响打分的结果。

这个问题比较有趣的讨论如下:

https://elasticsearch.cn/question/2275

3.17 集群统计

统计集群的两个方面信息:

一:索引层面

  • 分片数、存储大小、内存使用情况;

二:节点层面

  • 节点数量、节点角色、操作系统、JVM版本、内存、CPU、插件信息x-pack等。
1GET  /_cluster/stats

4、核心工具推荐

工欲善其事必先利其器,好的工具能提升开发效率。

4.1 Luke 工具

1、功能介绍:

查看Luncene、Solr、Elasitcsearch索引的GUI工具,方便开发和诊断。

2、核心功能点:

  • 查看分析字段内容;
  • 搜素索引;
  • 执行索引维护;
  • 从HDFS读取索引;
  • 将全部或者部分索引转换为XML格式导出。
  • 测试自定义的Lucene分词器。

3、工具地址:

https://github.com/DmitryKey/luke

4、最新版本

5、注意

Luke的版本要和Lucene一致。

4.2 Tika工具

1、简介

Apache Tika是一个用于文本检测和文件内容提取的库。

2、特点

Tika 可以检测超过1000种不同类型的文档,比如PPT、PDF、DOC、XLS,所有的文档类型可以通过一个简单的接口被解析。

3、应用

Tika广泛应用于搜素引擎、内容分析、文本翻译、数字管理等领域。

4、下载地址

http://tika.apache.org/download.htm

5、扩展

如果有全文知识库检索的项目,可以考虑使用Tika对多种不同类型的文档进行文档解析。

5、小结

此为拆解的第一本书,印证了我之前说的,核心知识点在Elasticsearch官网文档中都有更详尽的英文解读。

目前市面上没有一本书能涵盖全部的知识点。

书的目的多半是作者的一些学习、实践积累,更多的知识还得靠实践中总结、实践、再总结。

“书写是为了更好的思考”,与大家共勉!一起加油!

下一本书,紧张梳理中…..

推荐阅读:

《深入理解 Java 内存模型》读书笔记

面试-基础篇

Spring Boot 2.0 迁移指南

SpringBoot使用Docker快速部署项目

为什么选择 Spring 作为 Java 框架?

SpringBoot RocketMQ 整合使用和监控

Spring Boot 面试的十个问题

使用 Spring Framework 时常犯的十大错误

SpringBoot Admin 使用指南

SpringBoot Kafka 整合使用

SpringBoot RabbitMQ 整合使用

Elasticsearch索引增量统计及定时邮件实现

上篇好文:

Elasticsearch实战 | 必要的时候,还得空间换时间!

干货 |《从Lucene到Elasticsearch全文检索实战》拆解实践的更多相关文章

  1. 《从Lucene到Elasticsearch全文检索实战》的P184页

    curl -XPOST "http://localhost:9200/_bulk?pretty" --data-binary @books.json 这句话在书中是以crul的命令 ...

  2. Elasticsearch全文检索实战小结

    一.项目概述 这是一个被我称之为“没有枪.没有炮,硬着头皮自己造”的项目.项目是和其它公司合作的三个核心模块开发. 使用ES的目的是: 1).采集数据.网站数据清洗后存入ES: 2).对外提供精确检索 ...

  3. 开源搜索引擎评估:lucene sphinx elasticsearch

    开源搜索引擎评估:lucene sphinx elasticsearch 开源搜索引擎程序有3大类 lucene系,java开发,包括solr和elasticsearch sphinx,c++开发,简 ...

  4. Elasticsearch全文检索工具入门

    Elasticsearch全文检索工具入门: 1.下载对应系统版本的文件 elasticsearch-2.4.0.zip 1.1运行elasticsearch-2.4.0\elasticsearch- ...

  5. ElasticSearch 全文检索— ElasticSearch概述

    ElasticSearch 产生背景 1.海量数据组合条件查询 2.毫秒级或者秒级返回数据 Lucene 定义 lucene是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一 ...

  6. 使用Lucene.Net实现全文检索

    使用Lucene.Net实现全文检索 目录 一 Lucene.Net概述 二 分词 三 索引 四 搜索 五 实践中的问题 一 Lucene.Net概述 Lucene.Net是一个C#开发的开源全文索引 ...

  7. Lucene作为一个全文检索引擎

    Lucene作为一个全文检索引擎,其具有如下突出的优点: (1)索引文件格式独立于应用平台.Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件. ...

  8. 《从Lucene到Elasticsearch:全文检索实战》学习笔记五

    今天我给大家讲讲tf-idf权重计算 tf-idf权重计算: tf-idf(中文词频-逆文档概率)是表示计算词项对于一个文档集或语料库中的一份文件的重要程度.词项的重要性随着它在文档中出现的次数成正比 ...

  9. 《从Lucene到Elasticsearch:全文检索实战》学习笔记四

    今天我给大家讲讲布尔检索模型基本概念 布尔检索模型: 检索模型是判断文档内容与用户相关性的核心技术,以大规模网页搜索为例,在海量网页中与用户查询关键词相关的网页可能会有成千上万个,甚至耕读哦.那么信息 ...

随机推荐

  1. Codeforces Gym101201B:Buggy Robot(BFS + DP)

    题目链接 题意 给出一个n*m的地图,还有一个操作序列,你原本是要按照序列执行操作的,但是你可以修改操作:删除某些操作或者增加某些操作,问从'R'到'E'最少需要多少次修改操作. 思路 和上次比赛做的 ...

  2. HDU 6053:TrickGCD(莫比乌斯反演)

    题目链接 题意 给出n个数,问在这n个数里面,有多少组bi(1<=bi<=ai)可以使得任意两个bi不互质. 思路 想法就是枚举2~min(ai),然后去对于每个ai都去除以这些质数,然后 ...

  3. Elasticsearch(三) 插件安装

    1.head插件 命令:  ./bin/plugin install mobz/elasticsearch-head

  4. ASP.NET Core系列(一): .NET Core简介及安装开发环境

    大家都知道Java是跨平台的,.NET因为不具有跨平台的特性,被越来越多的开发者诟病,之前有各种间接的跨平台的方案,比如mono.但是由于各种兼容问题,最终 .NET Core出现了,它可以让程序在W ...

  5. android_layout_linearlayout(二)

    android的线性布局linearlayout的研究没有尽头.看了官网关于线性布局的一个例子,捣鼓一阵,发现的迷惑记录在此. 一.先看看官网xml <?xml version="1. ...

  6. Go语言设计模式汇总

    目录 设计模式背景和起源 设计模式是什么 Go语言模式分类 个人观点 Go语言从面世就受到了业界的普遍关注,随着区块链的火热Go语言的地位也急速蹿升,为了让读者对设计模式在Go语言中有一个初步的了解和 ...

  7. C# 中异常抛出捕获机制--throw / try,catch,finally

    try { messagebox.show("true"); } catch { messagebox.show("false"); } finally { m ...

  8. 在 Microsoft.VisualStudio.Setup.Engine.Install(Product product, String destination, CancellationToken token)无法在相同位置或现有实例“20cc4971”的子目录上安装指定实例“ebc82a8e”的解决方案

    在所在的安装目录根目录下搜索实例 如 20cc4971 将文件夹全部删除. 一般默认安装在C盘,所以在C盘搜索实例文件夹,将其全部删除.

  9. Mysql常用语法及入门开篇(一)

    数据:信息,记录.阅读: 数据库:数据的仓库,存储许多的数据(信息).按照数据结构来组件.存储和管理数据的,建立在计算机存储设备上的仓库. DBMS:   database management Sy ...

  10. Git的使用和配置小白必看都是干货,为您解惑

    Git安装 首先下载git这个软件,然后打开码云新建仓库 在本地选择一个路径作为本地仓库 点新建仓库然后输入邮箱和密码,然后进行配置 在要作为本地仓库的地方新建一个文件夹,保存后关闭,在文件夹空白处鼠 ...