Elasticsearch简单入门及应用
来源:
多年前,一个叫做Shay Banon的刚结婚不久的失业开发者,由于妻子要去伦敦学习厨师,他便跟着也去了。在他找工作的过程中,为了给妻子构建一个食谱的搜索引擎,他开始构建一个早期版本的Lucene。
直接基于Lucene工作会比较困难,所以Shay开始抽象Lucene代码以便Java程序员可以在应用中添加搜索功能。他发布了他的第一个开源项目,叫做“Compass”。
后来Shay找到一份工作,这份工作处在高性能和内存数据网格的分布式环境中,因此高性能的、实时的、分布式的搜索引擎也是理所当然需要的。然后他决定重写Compass库使其成为一个独立的服务叫做Elasticsearch。
第一个公开版本出现在2010年2月,在那之后Elasticsearch已经成为Github上最受欢迎的项目之一,代码贡献者超过300人。一家主营Elasticsearch的公司就此成立,他们一边提供商业支持一边开发新功能,不过Elasticsearch将永远开源且对所有人可用。
特点:
elasticsearch是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
几乎每个系统都会有一个搜索的功能,当搜索做到一定程度时,维护和扩展起来难度就会慢慢变大,所以很多公司都会把搜索单独独立出一个模块,用ElasticSearch等来实现。
Elasticsearch还可用来做日志分析系统:ELK。是ElasticSearch + Logstash +Kibana 的简称。L:是一个完全开源的工具,他可以对你的日志进行收集、分析,并将其存储供以后使用(如,搜索)。 kibana 也是一个开源和免费的工具,他 Kibana 可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。
ElasticSearch的使用非常广泛。例如:UBER、LinkedIn、ebay等公司。
安装:
1、下载地址
https://www.elastic.co/downloads
2、两种运行方式:
第一种:直接解压,找到bin目录,然后运行程序,用nohup或者elasticsearch –d,
https://www.elastic.co/guide/en/elasticsearch/reference/current/setup.html
第二种:以系统服务的形式运行(推荐这种)
官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-service.html
gitHub:
https://github.com/elastic/elasticsearch-servicewrapper
3、elasticsearch-head
辅助管理集群的可视化工具,可以用来查询数据和查看管理集群。
gitHub:
https://github.com/mobz/elasticsearch-head
4、插件
Elasticsearch本身不支持中文,需要下插件以支持中文分词
https://www.elastic.co/guide/en/elasticsearch/plugins/current/analysis-smartcn.html
如果还嫌麻烦,可以直接去gitHub上看一看“elasticsearch-rft”这个项目,直接集成了elasticSearch所需的所有中文东西。https://github.com/medcl/elasticsearch-rtf
5、http client
这里选用的是官方提供的elasticsearch-php
https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
elasticsearch创建:
1、ElasticSearch中数据名称和数据库中的对应关系
index ~~ database
type ~~ table
document ~~ row
2、创建index的结构
不创建也可以,elasticsearch本身有一些默认的配置,但是一般都是自己创建。
PUT /my_index
{
"settings": { ... any settings ... },
"mappings": {
"type_one": { ... any mappings ... },
"type_two": { ... any mappings ... },
...
}
创建好的结构PHP版:
....
由于代码很长,我就不贴了
大体结构是
body:{
settings:{
number_of_shards:
number_of_replicas:
analysis { filter:{}, tokenizer:{}, analyzer:{} }
},
mappings:{
“your_type1”:{ … properties:{ id:{ type:long … } … }
…
}
}
3、索引设置
(Elasticsearch 提供了优化好的默认配置。除非你明白这些配置的行为和为什么要这么做,请不要修改这些配置。)
number_of_shards : elasticsearch 主分片点的个数 (默认是5)
number_of_replicas:每个分片的副本 (默认是1)
分片:
当有大量的文档时,由于内存、硬盘等硬件资源的能力,没法及时的相应客户端的请求,一个节点就不够用。这时候,数据可以分为较小的称之为分片(shard)的部分。每个分片可以放在不同的服务器上,因此,数据可以在集群节点中传播,当你查询的索引分布在多个分片上时,Elasticsearch会把查询发送给每个相关的分片,并将结果合并在一起,应用程序对于分片来讲是透明的(不知道也无需知道分片的存在)。
副本:
为了提高查询的吞吐量,可以使用副本。副本只是一个分片的精确复制,每个分片可以有零到多个副本。换句话说:Elasticsearch可以有许多相同的分片,其中之一被自动选择去更改索引操作。这种特殊的分片称之为:主分片(primary shard),其余的称之为副本分片(replica shard)。在主分片丢失的时候,例如该分片数据所在的服务器不可用,集群将副本提升为新的主分片。
analysis 机制用于进行全文本(Full Text)的分词,以建立提供搜索用的反向索引。
analysis 机制包含了一下步骤:
首先,把一整块的文本分割成单独独立的用于倒排索引的词(terms)。
然后,把这些分词整合成用于改善查询或其他操作的标准的结构。
以上工作被analyzers完美的解决了。一个analyzers是一个整合了以下三个东西的wrapper:
Character filters(字符过滤器):
首先字符串经过字符过滤器(character filter),它们的工作是在标记化前处理字符串。字符过滤器能够去除HTML标记,或者转换"&"为"and"。
Tokenizer(分词器):
下一步,分词器(tokenizer)被标记化成独立的词。一个简单的分词器(tokenizer)可以根据空格或逗号将单词分开(这个在中文中不适用)。
filters(过滤器):
最后,每个词都通过所有标记过滤(token filters),它可以修改词(例如将"Quick"转为小写),去掉词(例如停用词像"a"、"and"``"the"等等),或者增加词(例如同义词像"jump"和"leap")
注意:整个流程就是 character filters => Tokenzier => Tokenzier filters
elastic提供了很多开箱即用的字符过滤器、分词器和过滤器,可以参照官网。
https://www.elastic.co/guide/en/elasticsearch/guide/current/analysis-intro.html
中文版:
http://es.xiaoleilu.com/052_Mapping_Analysis/40_Analysis.html
这种DSL的东西没有必要记,现用现查就行了
以下是ElasticSearch内置的Analyzer、tokenizer、tokenizer filter、character filter
Analyzer(分析器):
Analyzer名字 | 作用 |
---|---|
standard | standard tokenizer, standard filter, lower case filter, stop filter |
simple | lower case tokenizer |
stop | lower case tokenizer, stop filter |
keyword | 不分词,内容整体作为一个token(not_analyzed) |
whitespace | 正则表达式分词,默认匹配\W+ |
lang | 各种语言 |
snowball | standard tokenizer, standard filter, lower case filter, stop filter,snowball filter |
custom | 一个Tokenizer, 零个或多个Token Filter, 零个或多个Char Filter |
tokenizer
standard | |
edgeNGram | |
keyword | 不分词 |
letter | 按单词分 |
lowercase | letter tokenizer, lower case filter |
nGram | |
whitespace | 以空格为分隔符拆分 |
pattern | 定义分隔符的正则表达式 |
uax_url_email | 不拆分url和email |
path_hierarchy | 处理类似/path/to/somthing样式的字符串 |
token filter
tokenizer filter名字 | tokenizer filter的作用 |
standard | |
asciifolding | |
length | 去掉太长或者太短的 |
lowercase | |
nGram | |
edgeNGram | |
porterStem | 波特词干算法 |
shingle | |
stop | 移除 stop words |
word_delimiter | 将一个单词再拆成子分词 |
stemmer | |
stemmer_override | |
keyword_marker | |
keyword_repeat | |
kstem | |
snowball | |
phonetic | 插件 https://github.com/elasticsearch/elasticsearch-analysis-phonetic |
| 处理同义词 |
dictionary_decompounder,hyphenation_decompounder | 分解复合词 |
reverse | 反转字符串 |
elision | 去掉缩略语 |
truncate | 截断字符串 |
unique | |
pattern_capture | |
pattern_replace | 用正则表达式替换 |
| 去掉空格 |
limit | 限制token数量 |
hunspell | 拼写检查 |
common_grams | |
arabic_normalization,persian_normalization |
character filter 的名字 | character filter的作用 |
mapping | 根据配置的映射关系替换字符 |
html_strip | 去掉HTML元素 |
pattern_replace | 用正则表达式处理字符串 |
ElasticSearch的基本用法:
elasticsearch的curd操作很简单:
创建 index:curl-XPUT'localhost:9200/customer?pretty'
创建 document:curl-XPUT'localhost:9200/customer/external/1?pretty'-d'{ "name": "John Doe"}'
删除 index : curl-XDELETE'localhost:9200/customer?pretty'
删除document: curl-XDELETE'localhost:9200/customer/external/2?pretty'
note:删除了index,index下面的所有document都会删除。
修改: curl-XPOST'localhost:9200/customer/external/1/_update?pretty'-d'{ "doc": { "name": "Jane Doe" }}'
查找:elasticSearch的查找可以非常复杂,也可以简单。
简单的:curl-XGET'http://localhost:9200/twitter/tweet/1'
这样可以直接得到我们需要的那个document的信息
但是我们检索肯定不能这么简单,elasticsearch提供了一套查询的DSL,专门用于Query,可以去官网仔细看一下,这里就不过多赘述了
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-template.html
elasticsearch基本的API格式 curl -X请求方法(大写) IP地址 :port/ES中定义的Index/ES中定义的type/document的ID。注意:elasticsearch的增加是用的PUT方法,更新是POST方法,这和一般的REST规范有所不同。
elasticsearch还支持批量处理
例如:先更新一个数据,然后删除另一个数据,就可以这样写:
curl-XPOST'localhost:9200/customer/external/_bulk?pretty'-d'
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
'
elasticsearch的集群搭建:
创建三个节点的集群:
ElasticSearch创建集群非常的简单,把三个服务器中的elasticsearch.yml文件中的”cluster.name”改为相同的名字就可以。
然后把三个节点启动就可以,无需考虑任何问题,非常的方便。
ElasticSearch在项目中的应用
1、创建index
创建index需要考虑的东西很多:需要几个type?需要document的结构是怎样的?字段需要几种分词?等等。Index重要的分析机制是自定义的,以后想要检索得到更好的结果,主要是优化这一部分。
2、在程序中使用elasticsearch-PHP,来向ES发送rest请求。
添加一个document:
添加一个index:
删除一个document:
删除一个index:
得到一个document:
修改一个document:(官网贴图没找到)
(PS:其中data是一个php数组)
查询比较多样和复杂在此,我贴一个项目中用到的,功能:多种type联合搜索后,根据“城市”过滤结果,然后高亮显示match上的字段。
$param = [
'index' => ESConsts::INDEX,
'type' => [ESConsts::TYPE_DOC, ESConsts::TYPE_HOSPITAL],
'body' => [
'size' =>9000,
'from' =>0,
'query' => [
'filtered' => [
'query' => [
"multi_match" => [
"query" => $keyword,
"type" => "best_fields",
"fields" => [
"name", "hospitals_name",
"hospitals_name.hospitals_name_pinyin", "name.name_pinyin"
],
"tie_breaker" => 0.3,
"minimum_should_match" => "10%"
],
],
'filter' => [
'term' => ['city' => $city]
],
]
],
'highlight' =>[
'fields' => [
'hospitals_name' => [
"pre_tags" => ["<font color='#00FFFF'>"],
"post_tags" => ["</font>"]
],
'name' => [
"pre_tags" => ["<font color='#00FFFF'>"],
"post_tags" => ["</font>"]
],
'hospitals_name.hospitals_name_pinyin' => [
"pre_tags" => ["<font >"],
"post_tags" => ["</font>"]
],
'name.name_pinyin' => [
"pre_tags" => ["<font >"],
"post_tags" => ["</font>"]
]
]
]
]
];
$response = $client->search($param);
3、ES和DB数据的一致性
ES中的数据必须要保持和DB数据的一致,才可以得到真实的结果,否则,用户通过ES得到的数据永远都是不可用的。在项目中是通过重写model层的写库方法实现的,每当对DB进行写操作的时候,触发事件,异步向ES中发消息,然后更改ES中数据。
(通过 PHP 框架 Laravel 的Event模块实现)
更多精彩内容,请关注我的微信公众账号 互联网技术窝
更多推荐
所有评论(0)