您的位置:首页 > 其它

ELK之Elasticsearch介绍及在搜索中的使用

2016-06-06 15:39 549 查看

ELK: Elasticsearch + Logstash + Kibana

Elasticsearch: 是一个分布式的、实时全文搜索及分析引擎;检索性能高效是最大的特色。

Logstash: 是一个数据收集器,有丰富的插件(input/filter/output)。

Kibana: 是一个基于Elasticsearch的web展示平台。

Elasticsearch的基本概念

近实时(Near Realtime): 从一个doc被索引到能够查询到, 大约有1秒的间隔

index: 索引,类似SQL中的database, NoSQL中的database

type: 一个index下, 可以有多个type, 类似SQL中的table, NoSQL中的collection

document: 某index/type下的一条数据,以json的格式。类似SQL中的row,NoSQL中的document.

MySQL
database
table
row
mongodb
database
collection
document
ES
index
type
document
shard: 一个index可以有多个shards,默认是5。目的是,方便水平扩容和提高负载。一旦index被创建,shards的数量不能再改。每个shard,就是一个Lucene的index。一个Lucene的index能够容纳的documents的数量上限是2,147,483,519
(= Integer.MAX_VALUE - 128)

replica: 一个index的备份数,默认是1。目的是,提高可靠性,加快search的速度。replicas的数量可以随时修改。e.g.
http://10.16.25.16:9000/_plugin/head/

node:

cluster: one or more nodes with same cluster name

Schemaless or not

在某种意义上,ES是schemaless的, 在索引doc的时候, 直接指定index/type就可以了,无需对index/type进行任何的设定。实际上, 在index/type被创建的时候,ES会去猜json里面的字段,然后自动生成一份mapping(mapping是对doc中,
各字段的类型的定义, 及索引方式等的解析)。

一旦有了mapping, 就变成schema的了,doc里面已有的字段类型 就不能随意更改了。

template and mapping

mapping:用来说明doc里面的各个字段的类型, 以及如何存储和索引。mapping依赖于index,
不同的type有不同的mapping。mapping中的字段类型, 一旦创建,不能修改,但可以新增字段。

template:在index被创建的时候, 提供index的setting以及需要的mapping,先于index存在,且只在index 被创建的时候生效,一旦索引被创建,修改template就不会对已经创建的index生效了。

ES的三个基本问题之写入数据

ES使用了2个端口9200和9300(默认)

9200负责HTTP的请求

e.g. curl -XPUT http://esnode:9200/index/type -d ‘{json_doc}’

9300是TCP端口,供ES nodes之间通信使用。

写数据到ES,所使用的clients分成2种,

第一是JAVA的,第二是其它。

先说其它的(python/go/...等),都是用的是http REST api的方式,即访问的是9200.

再说JAVA client,根据角色的不同, 用分成2种,

其一,节点client(node client)即,java client成为ES cluster中的一个节点,但不存储数据。

其二,传输client(transport client),即java client不加入ES cluster, 只是传输数据给ES cluster中的节点。JAVA client使用的都是9300端口, 使用的是Elasticsearch的传输 协议(native
Elasticsearch transport protocol)。

Java 的客户端的版本号必须要与 Elasticsearch 节点所用的版本号一样,不然他们之间可能无法识别

ES的三个基本问题之读取数据

通过doc ID直接获取

e.g.
curl -XGET xxxx/yyyy/AVQvYyK6aK8LxcWQ324f

and the return

{"_index":"xxxx”,"_type":"yyyy","_id":"AVQvYyK6aK8LxcWQ324f”,

"_version":1,"found":true,

"_source”:{json_doc}

}

通过_search获取,size default 10

GET
/index/type/_search?q=last_name:Smith
GET
/index/type/_search

{

"query" : {

               "match" : {

                   "last_name" : "Smith"

               }

           }

}

通过_scroll来获取大量数据,类似database的游标

一般用于reindex

ES的三个基本问题之性能优化

CPU/内存/SSD磁盘
除了官网上介绍的,ES_HEAP_SIZE/swap
off/bootstrap.mlockall等
translog.durability:”async”,这个对写的性能影响巨大,

默认是request,即每当有增删改操作时, 就会触发flush/commit to Lucene(磁盘IO)

ES的字段类型及index



若没有mapping,
ES会根据上面的规则去guess
若有mapping,ES会根据mapping对字段进行匹配及转换

e.g. 某字段在mapping中是number,而doc里面是 “123”,则会被自动转成123;“cde”则会报错

ES中, 不同类型的字段, ES的处理方式是不同的。对于非string字段, ES会原样索引;对于string类型的字段,index类型有:no/not_analyzed/analyzed

no
not_analyzed
analyzed(默认)
不索引,该字段无法search
不分析,原样索引
只对string字段,先分析(分词),然后索引
analyzer: 对于index:analyzed的string类型的字段, 使用哪种analyzer(when index and also search), 默认是standard,对于中文, 会切成单字,搜索中会使用IK

DSL介绍


1) match_all

{ "match_all": {}} 匹配所有的, 当不给查询条件时,默认。


2) match

进行full text search或者exact value(非string字段或not_analyzed的字段),进行匹配


3) multi_match

同时对多个字段进行同样的match

{

   "multi_match": {

       "query":    "full text search",

       "fields":   [ "title", "body" ]

   }

}


4) range

对number或时间字段进行

{

   "range": {

       "age": {

           "gte":  20,

           "lt":   30

       }

   }

}


5) term

对字段进行确切值(exact value)的查询,如数字、时间、bool、not_analyzed字段等。

{ "term": { "age":    26           }}

{ "term": { "date":   "2014-09-01" }}

{ "term": { "public": true         }}

{ "term": { "tag":    "full_text"  }}


6) terms

和term一样, 不同的是,可以指定多个值来进行精确匹配

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}


7) exists/missing

用来查找某个字段是否有值, 类似SQL中的 not is_null/is_null

{

   "exists":   {

       "field":    "title"

   }

}


8) bool 用来连接一系列的查询子句:包括must/must_not/filter/should

{

   "bool" : {

       "must" : {

           "term" : { "user" : "kimchy" }

       },

       "filter": {

           "term" : { "tag" : "tech" }

       },

       "must_not" : {

           "range" : {

               "age" : { "from" : 10, "to" : 20 }

           }

       },

       "should" : [

           {

               "term" : { "tag" : "wow" }

           },

           {

               "term" : { "tag" : "elasticsearch" }

           }

       ]

   }

}

query VS filter

除了需要匹配程度的查询(有_score的情况)使用query, 其余的查询都应该使用filter。(As a general rule, use query clauses for
full-text
search or for any condition that should affect the relevance score,
and use filters for everything else.)

filter的结果是会被ES缓存的, 以此来提高效率。

另外, filter由于不计算分数及排序, 所以, 速度较 query要快。

GET _search

{

 "query": {

   "bool": {

     "must": [

       { "match": { "title":   "Search"        }},

       { "match": { "content": "Elasticsearch" }}  

     ],

     "filter": [

       { "term":  { "status": "published" }},

       { "range": { "publish_date": { "gte": "2015-01-01" }}}

     ]

   }

 }

}

script

ES支持使用script。(script
fields, script score)
groovy
default script language
script默认是被禁止的,
需要在config/elasticsearch.yml中打开
script.inline:
true

script.indexed: true
script有4种:inline/file/indexed/plugin

1)
inline

GET
/_search
{
 "script_fields":
{
   "my_field":
{
     "script":
{
       "inline":
"1 + my_var",
       "params":
{
         "my_var":
2
       }
     }
   }
 }
}


2) file

存放的位置:config/scripts/my_script.groovy

GET /_search

{ "script_fields":

{ "my_field": {

"script": {

"file": "my_script",

"params": { "my_var": 2 }

}

}

}

}


3) indexed

将脚本存储在ES内, index as .script, 然后通过ID访问。

curl
-XPOST
localhost:9200/_scripts/groovy/indexedCalculateScore
-d
'{
    "script":
"log(_score * 2) + my_modifier"
}'

{
  "script_score":
{
    "script":
{
      "id":
"indexedCalculateScore",
      "lang"
:
"groovy",
      "params":
{
        "my_modifier":
8
      }
    }
  }
}


4) plugin

需要install到ES

{
   "script_score":
{
     "script":
{
         "inline":
"my_script",
         "lang"
:
"native"
     }
   }
 }

ssh://git.wandoulabs.com:29418/es-search
es-search/es-score下有MyNativeScript*.java是个示例,
比较方便。

function_score

doc
and source:

使用source可以访问doc的原值,但速度较慢(not loaded into memory), 访问时需要经历loaded -> parsed的过程。
doc可以访问not_analyzed的字段的值,e.g.
doc[‘field_name’].value

速度的优化措施:
0)
使用doc, 不使用source,使用source慢得离谱了。因为doc已经在内存里了
1)
增加shards数及ES node数, 结果不是很明显
2)
使用size, 发现只是展示的doc的数量变化, 对于速度无影响
3)
terminate_after: 在每个shards上, 只search前N个doc, 不实际,无法保证结果。
4)
增加filter, 使得进行二次打分的doc数量极大的降低, 来提高速度。

IK分词

对于string字段,
默认使用的analyzer是standard,对中文会分成单字,效果不好。
对于title等字段,
增加子字段, fields: title.cn, 使用"analyzer": "ik"进行分析。

"mappings":
{
   "my_type":
{
     "properties":
{
       "text":
{
         "type":
"string",
         "fields":
{
           "english":
{

             "type":
    "string",
             "analyzer":
"english"
           }
         }
       }
     }
   }
 }

查询的时候,可以使用多个字段

{
 "query":
{
   "multi_match":
{
     "query":
"quick brown foxes",
     "fields":
[
       "text",
       "text.english"
     ],
     "type":
"most_fields"

   }
 }
}
将下载量大于100000的app_doc(不到6000个)的title放入字典,
提高分词的效果。

plugins

各种很有用的ES的插件以及辅助工具等。
kibana:
ES的web 界面及自定义的dashboard
marvel:
ES的性能实时监控数据及展示
head:
ES索引及数据的浏览及管理
sense:
json化的ES访问工具
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Elasticsearch