centos安装elasticsearch
- 导入密钥
rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch
2.增加资源配置库
在/etc/yum.repos.d目录下,增加yum资源库
[elasticsearch-2.x]
name=Elasticsearch repository for 2.x packages
baseurl=https://packages.elastic.co/elasticsearch/2.x/centos
gpgcheck=1
gpgkey=https://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1
3.安装
yum install elasticsearch
安装目录为:/usr/share/elasticsearch
4.配置开机自启动
chkconfig --add elasticsearch
安装中文分词IK插件
- 下载源代码
git clone https://github.com/medcl/elasticsearch-analysis-ik.git
2.打包
mvn package
- 复制插件
把打包目录target/release下的elasticsearch-analysis-ik-1.9.5.zip复制到 elasticsearch安装目录下面。 如: /usr/share/elasticsearch/plugins/ik
4.配置
plugins/ik/config/IKAnalyzer.cfg.xml
可以直接配置词典和自定义词典
修改默认分词器
修改elasticsearch.yml配置文件,增加
#默认分词器,索引
index.analysis.analyzer.default.type: ik
#默认分词器,查询
index.analysis.analyzer.default_search.type: ik
使用步骤
- 创建索引
curl -XPUT http://localhost:9200/index
- 创建索引时指定文档的索引
curl -XPUT http://192.168.2.10:9200/traffic?pretty -d '
{
"mappings": {
"robot": {
"properties": {
"question": {
"include_in_all": true,
"analyzer": "ik_syno",
"term_vector": "with_positions_offsets",
"boost": 8,
"store": true,
"type": "string"
}
}
}
}
}
'
表示traffic引用、robot类型的,question字段使用ik_syno分析器
安装验证
查看启动结果
curl -XGET http://127.0.0.1:9200/?pretty
日志
/var/log/elasticsearch/elasticsearch.log
映射mapping
定义了一个文档怎么被映射到搜索引擎,例如哪些引擎是可以被搜索的,以及他们怎么样被分词。
显示映射是定义在index/type层次上的。默认情况下不需要定义显示映射的,因为ES会默认帮我们创建,但是我们也可以改写ES创建的默认mapping。
document字段映射类型分为analyzed、not_analyzed、no
- analyzed
字段被分析、分词、索引,可以被检索。 - not_analyzed
字段不被分析、但是可以精确检索 no
字段不被分析、索引,不能检索。分析器
分析器包含三个功能,即字符过滤器、分词器、标记过滤。
- 字符过滤器
在标记前处理字符串,如去除HTML标记,或者转换&为and. 分词器
标记独立的词。如一个简单的分词器(tokenizer)可以根据空格或者逗号将单词分开。标记过滤
每个词通过所有标记过滤器,可以修改词,去掉词,或者增加词(如同义词)
- 字符过滤器
查看分词结果
查看默认分词结果
curl -XGET 'http://192.168.2.10:9200/traffic/_analyze?field=brand_name&pretty' -d '童装童鞋’
查看指定分词器分词结果
curl -XGET 'http://192.168.2.10:9200/traffic/_analyze?tokenizer=ik&field=brand_name&pretty' -d '童装童鞋'
curl -XGET 'http://192.168.2.10:9200/traffic/_analyze?tokenizer=standard&field=brand_name&pretty' -d '童装童鞋'
配置同义词
修改elasticsearch.yml,增加
index:
analysis:
analyzer:
ik_syno:
type: custom
tokenizer: ik_max_word
filter: [my_synonym_filter]
ik_syno_smart:
type: custom
tokenizer: ik_smart
filter: [my_synonym_filter]
filter:
my_synonym_filter:
type: synonym
synonyms_path: analysis/synonym.txt
在elasticsearch.yml同目录下的analysis子目录下,建立synonym.txt文件,格式为UTF-8。
格式为:
驾驶证,驾照
格式说明:
表示 出现a或者b,则相互分词.
a,b => c
a,b,c
第一种在分词的时候,a,b都会解析成为c,然后把c存入索引中
第二种在分词的时候,有a的地方,都会解析成a,b,c,把a,b,c存入索引中
第一种方法相比之下有个主词,比较省索引。
常见接口
- 创建索引
curl -XPUT http://ip:port/traffic?pretty -d '
{
"mappings": {
"robot": {
"properties": {
"question": {
"include_in_all": true,
"analyzer": "ik_syno",
"term_vector": "with_positions_offsets",
"boost": 8,
"store": true,
"type": "string"
}
}
}
}
}
'
- 增加文档
curl -XPUT http://ip:port/traffic/robot/1 -d '
{
"question": "对酒驾行为如何记分",
"answer":"酒驾行为属于严重违法行为。公安部123号令作出了对饮酒后驾驶机动车的记12分的规定。饮酒后驾驶营运机动车、醉酒后驾驶营运或非营运机动车,吊销驾驶证。",
"type":"酒驾"
}'
- 查询
查询所有的类型下的文档
curl -XGET 'http://ip:port/traffic/_search?pretty'
查询特定类型下的文档
curl -XGET 'http://ip:port/traffic/robot/_search?pretty'
查询特定类型下的文档
curl -XGET 'http://ip:port/traffic/robot/_search?pretty' -d '{
"query" : {
"query_string" : {
"query" : "记分周期",
"fields" : [ "question" ]
}
}
}'
- 删除文档
curl -XDELETE http://ip:port/traffic/robot/1
- 查看相关性的分析
curl -XGET http://ip:port/traffic/robot/_search?explain -d '
{
"query": {
"term": {
"question": "闯红灯"
}
}
}'
6.查询在不同字段中的权重
GET /_search
{
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "quick brown fox",
"boost": 2 #1
}
}
},
{
"match": { #2
"content": "quick brown fox"
}
}
]
}
}
}
- title 查询语句的重要性是 content 的2倍,因为它的权重提升值为2。
- 一个没有设置权重提升的查询语句的值为1。
术语
字段映射mapping中not_analyzed表示该字段不进行分析,作为精确值处理
term过滤器
包含,只要出现即可,不参与记分基于term术语的查询
只对反向索引的术语进行精确匹配- 基于全文的查询(Full-text queries)
如match或query_string这样的高层次查询,它知道一个字段的映射: - 如果用来查询时间或者整数(integer),会讲查询字符串分别当做时间或者整数
- 如果查询一个准确的(未分析过的not_analyzed)字符串字段,它会整个查询字符串当做一个术语
- 如果查询一个全文字段(分析过的analyzed),它会讲查询字符串传入到一个合适的分析器,然后生成一个供查询的术语列表。
一旦查询组成了一个术语列表,它会将每个术语逐一执行低层次的查询,然后将结果合并,为每个文档生成一个最终的相关性分数。
-dis_max
dis_max分离最大化查询(Disjunction Max Query)。分离的意思是或(or),这与把结合(conjunction)理解成(and)对应。分离最大化查询是指,将任何与任一查询匹配的文档作为结果返回,但是只将最佳匹配的分数作为查询的结果分数。
当想要准确查询一个未分析过的(not_analyzed)的字段之前,需要考虑是需要查询还是过滤。
-tie_break
使用tie_break参数将其它匹配语句的分数也考虑其中:
{
“query”: {
“dis_max”: {
“queries”: [
{ “match”: { “title”: “Quick pets” }},
{ “match”: { “body”: “Quick pets” }}
],
“tie_breaker”: 0.3
}
}
}
tie_breaker参数提供了一种处于dis_max和bool中间状态的查询,它分数计算的方式如下:
1.获得最佳匹配(best-matching)语句的分数 *_score*
2.将其他匹配语句的得分和tie_breaker向乘
3.讲以上分数求和并规范化(normalize)
注意:
tie_breaker 可以是 0 到 1 之间的浮点数,其中,如果数值为0,即代表使用dis_max最佳匹配语句的普通逻辑,如果数值为1,即表示所有匹配语句同等重要。最佳的准确值需要根据数据与查询进行调试得出,但是合理的值通常与零接近(处于 0.1 - 0.4 之间),这样的合理值不会改变 dis_max 使用最佳匹配的本质。
-词频(term frequencies)
默认使用的相似度算法是TF/IDF
词频是指,一个词在单个文档中的某个字段出现的频率越高,这个文档的相关度越高
-逆向文件频率(Inverse document frequency)
一个词在所有文档索引中出现的频率越高,这个词的相关度越低。
分析过程
- 单个词查询
释使用 match 在全文字段中使用单个词进行查找:
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": "QUICK!"
}
}
}
ElasticSearch执行上面这个 match 查询的步骤是:
检查字段类型(Check the field type)
标题 title 字段是一个全文(analyzed) string 类型的字段,这意味着查询字符串本身也需要被分析(analyzed)。
分析查询字符串(Analyze the query string)
将查询的字符串 QUICK! 传入标准的分析器中(standard analyzer),输出的结果是 quick。因为对于单个术语,match 查询处理的是低层次的术语查询。
查找匹配文档(Find matching docs)
term 查询在反向索引中查找 quick 然后获取一组包含有术语的文档,在这个例子中为文档:1,2和3。
为每个文档计算分数(Score each doc)
term 查询为每个文档计算相关度分数,将术语频率(term frequency),即quick词在相关文档title中出现的频率,和反向文档频率(inverse document frequency),即quick在所有文档title中出现的频率,以及字段的长度,即字段越短相关度越高。
这个过程给我们的结果为:
"hits": [
{
"_id": "1",
"_score": 0.5, #1
"_source": {
"title": "The quick brown fox"
}
},
{
"_id": "3",
"_score": 0.44194174, #2
"_source": {
"title": "The quick brown fox jumps over the quick dog"
}
},
{
"_id": "2",
"_score": 0.3125, #3
"_source": {
"title": "The quick brown fox jumps over the lazy dog"
}
}
]
1 文档1最相关,因为title更短,即quick占有内容的很大一部分。
2、3 文档3 比 文档2 更相关,因为在文档2中quick出现了2次。
- 多词查询(Multiword Queries)
如果我们一次只能搜索一个词,那么全文搜索会非常不灵活,幸运的是,ElasticSearch的 match 查询让多词查询非常简单:
GET /my_index/my_type/_search
{
"query": {
"match": {
"title": "BROWN DOG!"
}
}
}
上面这个查询返回了所有四个文档:
{
"hits": [
{
"_id": "4",
"_score": 0.73185337, #1
"_source": {
"title": "Brown fox brown dog"
}
},
{
"_id": "2",
"_score": 0.47486103, #2
"_source": {
"title": "The quick brown fox jumps over the lazy dog"
}
},
{
"_id": "3",
"_score": 0.47486103, #3
"_source": {
"title": "The quick brown fox jumps over the quick dog"
}
},
{
"_id": "1",
"_score": 0.11914785, #4
"_source": {
"title": "The quick brown fox"
}
}
]
}
1 文档4是最为相关的,因为它包含词“brown”两次以及“dog”一次。
2#3 文档2、3同时包含brown 和 dog 各一次,而且他们title的长度相同,所以有相同的分数。
4 文档1 也能匹配,尽管它只有 brown 而没有 dog。
因为 match 查询查找两个词 [“brown”, “dog”],内部实际上它执行两次 term 查询,然后将两次查询的结果合并为最终结果输出。为了这么做,它将两个term查询合并到一个bool查询中。
这告诉我们一个重要的结果,即任何文档只要是title里面包含了任意一个词,那么就会匹配上,被匹配的词越多,最终的相关性越高。
分析器使用分析
索引时
- 在字段映射中定义的index_analyzer,否则
- 在字段映射中定义的analyzer,否则
- 在文档的_analyzer中指定的analyzer,否则
- 在type中指定的默认 index_analyzer,否则
- 在type中指定的默认 analyzer,否则
- 在index设置中指定的名为default_index的analyzer,否则
- 在index设置中指定的名为default的analyzer,否则
- 在node中指定的名为default_index的analyzer,否则
- 在node中指定的default的analyzer,否则
- 标准(standard)的analyzer
在搜索时
- 在query中定义的analyzer,否则
- 在字段映射中定义的search_analyzer,否则
- 在字段映射中定义的analyzer,否则
- 在type中指定的默认search_analyzer,否则
- 在type中指定的默认analyzer,否则
- 在index设置中指定的名为default_search的analyzer,否则
- 在index设置中指定的名为default的analyzer,否则
- 在node中指定的名为default_search的analyzer,否则
- 在node中指定的名为default的analyzer,否则
- 标准(standard)的analyzer.
phrase 匹配或者叫邻近度匹配(Proximity Matching)
短语匹配,表示有序行,如果设置slop=0,表示精确匹配。
match phrase查询首先解析字符串产生一个词条列表。然后搜索所有的词条,但只保留韩还有了所有搜索词条的文档,并且词条的位置要临近。
降低精确匹配的精度,采用slop参数。 slop参数告诉match_phrase查询词条能够相隔多远时,仍将文档视为匹配。相隔多远的意思是,需要移动一个词条多少次来让查询和文档匹配。
在配置了slop的短语匹配中,所有的单词都需要需要出现,但是单词的出现顺序可以不同。如果slop的值足够多,单面单词的顺序可以是任意的。
Pos 1 Pos 2 Pos 3
-----------------------------------------------
Doc: quick brown fox
-----------------------------------------------
Query: fox quick
Slop 1: fox|quick ↵
Slop 2: quick ↳ fox
Slop 3: quick ↳ fox
短语查询(Phrase Query)只是简单地将不含有精确查询短语的文档排除在外,而邻近查询(Proximity Query) - 一个slop值大于0的短语查询 - 会将查询词条的邻近度也考虑到最终的相关度_score中
通过设置一个像50或100这样的高slop值,你可以排除那些单词过远的文档,但是也给予了那些单词邻近的文档一个更高的分值。
尽管邻近度查询(Proximity Query)管用,但是所有的词条都必须出现在文档的这一要求显的过于严格了。这个问题和我们在全文搜索(Full-Text Search)一章的精度控制(Controlling Precision)一节中讨论过的类似:如果7个词条中有6个匹配了,那么该文档也许对于用户而言已经足够相关了,但是match_phrase查询会将它排除在外。
参考文档
- ElasticSearch文档分析系列
http://www.cnblogs.com/richaaaard/p/5243049.html