Elasticsearch

谈谈全文检索

作者注:最近,实验室有一个关于大数据全文检索的项目,主要架构采用了 Elasticsearch + Lucene ,并修改了部分源码,通过后缀数组代替 Lucene 原有的索引方式。因此,接触了一些全文检索相关的内容。偶然的机会,我在网络上看到 forfuture1978 关于 Lucene 的文章,觉得很受启发,深感有必要记录下来。我相信,本文也能很好地帮助您理解全文检索。本文部分内容出自 Lucene 原理与代码分析 ,感谢原作者的贡献。 0 写在前面 大数据时代,人们愈加重视数据的价值。在此之前,我们将数据存放在传统的关系型数据库(一个个数据表,由行列组成,格式固定),关系型数据库存储的是结构化数据,我们无法“用活”这些数据。事实上,绝大多数的数据都是以非结构化数据的形式存在的,比如邮件、图像、视频等等。这些大量的非结构化数据的价值是巨大的,但在关系型数据库下显然不好处理。 全文检索提供了对非结构化数据的信息搜索,使我们获得了处理这些数据的能力,我们可以在此基础上进一步提取这些数据的价值。 1 预备知识 1.1 数据分类 我们平时所说的数据,可分为结构化数据、半结构化数据和非结构化数据。 结构化数据:具有既定格式的实体化数据,如 XML 文档或满足特定预定义格式的数据库表; 半结构化数据:虽然可能有格式,但经常被忽略,所以只能作为对数据结构的一般性指导。如电子表格,它在结构上是由单元格组成的网格,但是每个单元格内可以保存任何形式的数据; 非结构化数据:无固定格式或不定长的数据,如纯文本、图像数据、邮件内容等。 1.2 数据搜索 数据的搜索根据数据的不同分类有所区别: 对结构化数据的搜索:如通过 SQL 语句对数据库的搜索等。 对非结构化数据的搜索:如 Linux 环境下的 grep 命令、 Google 搜索大量的内容数据等。 注:半结构化数据在本文将等同非结构化数据考虑。 2 什么是全文检索? 非结构化数据也可称为全文数据,对全文数据的搜索主要有两种方法。 (1)顺序扫描法(Serial scanning) 顺序扫描比较好理解,比如我们想在图书馆找某本书,那么我们就将整个图书馆的书一个一个比较,直到找到我们要找的书(当然现实中我们不会这么做)。 (2)全文检索(Full-text search) 全文检索的基本思路:将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定的结构,然后再对其进行搜索。也就是,将非结构化数据转化为结构化数据。 从非结构化数据中提取并重新组织的信息就叫做索引。索引其实我们早有接触,比如图书馆的图书索引,通过索引我们可根据图书的不同分类去特定的书架寻找,这样就无需寻找整个图书馆的所有书架。再比如,字典里通过汉字拼音的首字母分类,我们要在字典中寻找关于“搜索”的条目,只需找到首字母为 “S” 的分类即可。可见,索引可大大加快我们搜索的速度。 综上,对数据先建立索引,再通过索引搜索数据的过程就叫做全文检索。 下图为 Lucene 的检索原理,这其实也是全文检索的基本思路。通过对元数据建立索引信息,然后根据索引信息搜索数据。 3 索引应该存放哪些信息? 非结构化数据存放的是每个文件包含哪些字符串,这是从文件到字符串的映射。搜索的过程恰恰相反,我们想通过字符串搜索文件,也就是从字符串到文件的映射。 索引保存的正是从字符串到文件的映射,这也为什么是其能加快搜索速度的原因。

Elasticsearch实现批量更新

1 bulk 前面我们已经提到批量查询 mget ,那么如果我们想要批量导入数据呢?当然也有解决方法,那就是我们现在要讲的 bulk 。 bulk 允许我们使用单一请求来实现多个文档的 create 、 index 、 update 或 delete ,这在我们平时的应用中是很重要的。 2 bulk 语法 bulk API 对 JSON 的语法有严格的要求,具体要求:bulk 中每一个操作要两个 JSON 串,每个 JSON 串不能换行,只能放在同一行,而 JSON 串和 JSON 串之间,必须有一个换行。 bulk 允许我们批量执行不同的操作,常用操作如下: delete:删除文档,delete比较特殊,只需1个 JSON 串即可; create:相当于 PUT /index/type/id/_create,只不过是强制创建; index:普通的 PUT 操作,可以是创建文档,也可以是全量替换文档; update:执行 partial update 操作。 语法格式如下: POST /_bulk { {"action": {"metadata"}} //一个操作需两个JSON,delete除外 {"data"} } 举个栗子: 我们要创建一个文档,其中 index 为 “test_index” , type 为 “test_type” , id 为 1 ; field 有两个,分别是 test_field1 为 “test1” 、 test_field2 为 “test2” 。

Elasticsearch实现批量查询

1 批量查询 批量查询,就是一条一条的查询。比如说要查询100条数据,普通查询就要发送100次网络请求,这个开销是很大的。如果采用批量查询的话,查询100条数据,就只要发送1次网络请求,网络请求的性能开销缩减100倍。 2 mget 2.1 普通查询 ES 中查询数据最简单的方式就是通过 GET ,一次查询一条数据,如查询 id 为 1 和id 为 2 的数据。 GET /test_index/test_type/1 GET /test_index/test_type/2 2.2 批量查询 在 ES 中要实现批量查询可以通过 mget 来实现。 (1)查询 id 为 1 和id 为 2 的数据。 GET /_mget { "docs" : [ { "_index" : "test_index", "_type" : "test_type", "_id" : 1 }, { "_index" : "test_index", "_type" : "test_type", "_id" : 2 } ] } 查询结果:

Elasticsearch的乐观并发控制

0 前言 Elasticsearch 采用的是乐观锁并发控制,基于 Elasticsearch 提供的 _version 字段或我们自己定义的外部版本号,可以方便地实现乐观并发控制。 扩展阅读:并发控制(乐观锁、悲观锁) 1 基于 _version 的乐观并发控制 1.1 _version _version 是 ES 中提供的一个字段,它表明当前数据的版本号。我们可根据它来对比数据的版本是否一致。 1.2 操作实例 (1)构造一条数据。 PUT test_index/test_type/7 { "test_field":"test test" } (2)模拟两个客户端,获取同一条数据。 GET test_index/test_type/7 执行结果:两个客户端都能读到 id 为 7 的数据,版本号为 1 。 { "_index": "test_index", "_type": "test_type", "_id": "7", "_version": 1, "found": true, "_source": { "test_field": "test test" } } (3)一个客户端先更新数据,同时带上数据的版本号(?version=1)。确保 ES 中的数据版本号与客户端中的数据版本号是相同的才能修改。 PUT test_index/test_type/7?version=1 { "test_field":"test client 1" } 执行结果:修改成功,数据的版本号变为 2 。

Elasticsearch 初探

版权声明:本文由 Hov 所有,发布于 http://chenhy.com ,转载请注明出处。 0 前言 本文是我接触 Elasticsearch 后写下的第一篇文章,旨在通过电商网站商品管理的栗子来熟悉 Elasticsearch 的相关操作,可以说是学习 Elasticsearch 的第一个“Hello World”吧,后续将逐步深入 Elasticsearch 相关内容。 栗子中新增了三种品牌的牙膏“高露洁牙膏”、“佳洁士牙膏”、“中华牙膏”,并对这些数据进行增删改查、数据搜索、数据分析等操作。 注:本文操作环境为 Elasticsearch + Kibana 。 1 文档增删改查(CRUD) 1.1 新增文档,建立索引 格式: PUT /index/type/id { //JSON } 实例:新增商品(三种品牌的牙膏信息)。 PUT /ecommerce/product/1 { "name":"gaolujie yagao", "desc":"gaoxiao meibai", "price":30, "producer":"gaolujie producer", "tags":["meibai","fangzhu"] } PUT /ecommerce/product/2 { "name":"jiajieshi yagao", "desc":"youxiao fangzhu", "price":25, "producer":"jiajieshi producer", "tags":["fangzhu"] } PUT /ecommerce/product/3 { "name":"zhonghua yagao", "desc":"caoben zhiwu", "price":40, "producer":"zhonghua producer", "tags":["qingxin"] }