Elasticsearch使用总结 光环大数据

编辑:光环大数据 来源: 互联网 时间: 2018-02-12 14:30 阅读:

光环大数据人工智能培训机构,讲师都是实战专家,有十几年的软件开发经验和5年以上的实战经验,在业内口碑非常不错。强大的教研团队根据企业需要的技术研发出新的实用的教程,为保障学员就业与中关村软件园战略合作,并与学员签订就业协议保障就业,学员毕业后平均薪资8K以上,学员反馈口碑非常好!

  最初接触Elasticsearch是在ELK日志系统的建设中,随着对日志数据的消费越来越多,被其强大的数据搜索和分析能力所吸引;后来,在用户行为数据采集系统中,使用Elasticsearch做核心数据存储和实时聚合分析;再后来,使用Elasticsearch搭建了产品的搜索服务。目前来看,Elasticsearch在这三个系统中表现都很灵活和优异,没有让我们失望,而在系统建设中,我们也遇到过不少问题,有基本概念的迷惑、操作方法、部署、性能等等各个方面。本文着重对Elasticsearch在应用层面上的使用进行总结,搞清楚WHAT和HOW两个层面,即是什么、怎么用。

  NOTE:本文所述的概念和方法均在Elasticsearch2.3版本下。

基本概念

Elasticsearchisadistributed,RESTfulsearchandanalyticsenginecapableofsolvingagrowingnumberofusecases.AstheheartoftheElasticStack,itcentrallystoresyourdatasoyoucandiscovertheexpectedanduncovertheunexpected.

  这是官方对Elasticsearch的定位。通俗的讲,Elasticsearch就是一款面向文档的NoSQL数据库,使用JSON作为文档序列化格式。但是,它的高级之处在于,使用Lucene作为核心来实现所有索引和搜索的功能,使得每个文档的内容都可以被索引、搜索、排序、过滤。同时,提供了丰富的聚合功能,可以对数据进行多维度分析。对外统一使用RESTAPI接口进行沟通,即Client与Server之间使用HTTP协议通信。

  先来看存储上的基本概念,这里将其与MySQL进行了对比,从而可以更清晰的搞清楚每个概念的意义。

Elasticsearch    MySQL

index(索引,名词)    database

doctype(文档类型)    table

document(文档)    row

field(字段)    column

mapping(映射)    schema

queryDSL(查询语言)    SQL

  再来看倒排索引的概念(官方解释)。倒排索引是搜索引擎的基石,也是Elasticsearch能实现快速全文搜索的根本。归纳起来,主要是对一个文档内容做两步操作:分词、建立“单词-文档”列表。举个例子,假如有下面两个文档:

1.{"content":"Thequickbrownfoxjumpedoverthelazydog"}

2.{"content":"Quickbrownfoxesleapoverlazydogsinsummer"}

  最后,我们再回过头看看上面的映射的概念。类似于MySQL在dbschema中申明每个列的数据类型、索引类型等,Elasticsearch中使用mapping来做这件事。常用的是,在mapping中申明字段的数据类型、是否建立倒排索引、建立倒排索引时使用什么分词器。默认情况下,Elasticsearch会为所有的string类型数据使用standard分词器建立倒排索引。

查看mapping:GEThttp://localhost:9200/<indexname>/_mapping

NOTE:这里的index是blog,doctype是test

{

"blog":{

"mappings":{

"test":{

"properties":{

"activity_type":{

"type":"string",

"index":"not_analyzed"

},

"address":{

"type":"string",

"analyzer":"ik_smart"

},

"happy_party_id":{

"type":"integer"

},

"last_update_time":{

"type":"date",

"format":"yyyy-MM-ddHH:mm:ss"

}

}

}

}

}

}

数据插入

  在MySQL中,我们需要先建立database和table,申明dbschema后才可以插入数据。而在Elasticsearch,可以直接插入数据,系统会自动建立缺失的index和doctype,并对字段建立mapping。因为半结构化数据的数据结构通常是动态变化的,我们无法预知某个文档中究竟有哪些字段,如果每次插入数据都需要提前建立index、type、mapping,那就失去了其作为NoSQL的优势了。

直接插入数据:POSThttp://localhost:9200/blog/test

{

"count":5,

"desc":"helloworld"

}

查看索引:GEThttp://localhost:9200/blog/_mapping

{

"blog":{

"mappings":{

"test":{

"properties":{

"count":{

"type":"long"

},

"desc":{

"type":"string"

}

}

}

}

}

}

  然而这种灵活性是有限,比如上文我们提到,默认情况下,Elasticsearch会为所有的string类型数据使用standard分词器建立倒排索引,那么如果某些字段不想建立倒排索引怎么办。Elasticsearch提供了dynamictemplate的概念来针对一组index设置默认mapping,只要index的名称匹配了,就会使用该template设置的mapping进行字段映射。

  下面所示即创建一个名称为blog的template,该template会自动匹配以”blog_”开头的index,为其自动建立mapping,对文档中的所有string会自动增加一个.raw字段,并且该字段不做索引。这也是ELK中的做法,可以查看ELK系统中Elasticsearch的template,会发现有一个名为logstash的template。

创建template:POSThttp://localhost:9200/_template/blog

{

"template":"blog_*",

"mappings":{

"_default_":{

"dynamic_templates":[{

"string_fields":{

"mapping":{

"type":"string",

"fields":{

"raw":{

"index":"not_analyzed",

"ignore_above":256,

"type":"string"

}

}

},

"match_mapping_type":"string"

}

}],

"properties":{

"timestamp":{

"doc_values":true,

"type":"date"

}

},

"_all":{

"enabled":false

}

}

}

}

直接插入数据:POSThttp://localhost:9200/blog_2016-12-25/test

{

"count":5,

"desc":"helloworld"

}

  插入问题还有个话题就是批量插入。Elasticsearch提供了bulkAPI用来做批量的操作,你可以在该API中自由组合你要做的操作和数据,一次性发送给Elasticsearch进行处理,其格式是这样的。

action_and_meta_data\n

optional_source\n

action_and_meta_data\n

optional_source\n

....

action_and_meta_data\n

optional_source\n

比如:

{"index":{"_index":"test","_type":"type1","_id":"1"}}

{"field1":"value1"}

{"delete":{"_index":"test","_type":"type1","_id":"2"}}

{"create":{"_index":"test","_type":"type1","_id":"3"}}

{"field1":"value3"}

{"update":{"_id":"1","_type":"type1","_index":"test"}}

{"doc":{"field2":"value2"}}

  如果是针对相同的index和doctype进行操作,则在RESTAPI中指定index和type即可。批量插入的操作举例如下:

批量插入:POSThttp://localhost:9200/blog_2016-12-24/test/_bulk

{"index":{}}

{"count":5,"desc":"helloworld111"}

{"index":{}}

{"count":6,"desc":"helloworld222"}

{"index":{}}

{"count":7,"desc":"helloworld333"}

{"index":{}}

{"count":8,"desc":"helloworld444"}

查看插入的结果:GEThttp://localhost:9200/blog_2016-12-24/test/_search

数据查询

  Elasticsearch的查询语法(queryDSL)分为两部分:query和filter,区别在于查询的结果是要完全匹配还是相关性匹配。filter查询考虑的是“文档中的字段值是否等于给定值”,答案在“是”与“否”中;而query查询考虑的是“文档中的字段值与给定值的匹配程度如何”,会计算出每份文档与给定值的相关性分数,用这个分数对匹配了的文档进行相关性排序。

  在实际使用中,要注意两点:第一,filter查询要在没有做倒排索引的字段上做,即上面mapping中增加的.raw字段;第二,通常使用filter来缩小查询范围,使用query进行搜索,即二者配合使用。举例来看,注意看三个不同查询在写法上的区别:

1.只使用query进行查询:

POSThttp://localhost:9200/user_action/_search

查询的结果是page_name字段中包含了wechat所有文档

这里使用size来指定返回文档的数量,默认Elasticsearch是返回前100条数据的

{

"query":{

"bool":{

"must":[{

"match":{

"page_name":"wechat"

}

},

{

"range":{

"timestamp":{

"gte":1481218631,

"lte":1481258231,

"format":"epoch_second"

}

}

}]

}

},

"size":2

}

2.只使用filter进行查询:

POSThttp://localhost:9200/user_action/_search

查询的结果是page_name字段值等于"example.cn/wechat/view.html"的所有文档

{

"filter":{

"bool":{

"must":[{

"term":{

"page_name.raw":"example.cn/wechat/view.html"

}

},

{

"range":{

"timestamp":{

"gte":1481218631,

"lte":1481258231,

"format":"epoch_second"

}

}

}]

}

},

"size":2

}

3.同时使用query与filter进行查询:

POSThttp://localhost:9200/user_action/_search

查询的结果是page_name字段值等于"example.cn/wechat/view.html"的所有文档

{

"query":{

"bool":{

"filter":[{

"bool":{

"must":[{

"term":{

"page_name.raw":"job.gikoo.cn/wechat/view.html"

}

},

{

"range":{

"timestamp":{

"gte":1481218631,

"lte":1481258231,

"format":"epoch_second"

}

}

}]

}

}]

}

},

"size":2

}

聚合分析

  类似于MySQL中的聚合由分组和聚合计算组成,Elasticsearch的聚合也有两部分:Buckets与Metrics。Buckets,作为名词的话你可以理解为“桶”,意思是说聚合后的数据放在一个个桶里,也就是将数据分成多个组的意思,一个桶就是一个组别;作为动词,就是SQL中的分组groupby。Metrics,可以理解为“度量”,就是对桶里的数据进行某个运算,相当于SQL中调用聚合函数COUNT,SUM,MAX等。另外,聚合分析有时需要对多个字段值进行分组,在MySQL中,我们只要使用“groupbyc1,c2,c3”就可以完成这样的功能,但是Elasticsearch没有这样的语法。Elasticsearch提供了另一种方法,即Buckets嵌套,仔细想想,似乎这种设计更加符合人的思维方式。

  举例来看具体操作方法:

1.最简单的聚合查询

POSThttp://localhost:9200/user_action/_search

为了简单,这里删除了query的条件描述

将符合条件的文档按照公司进行聚合

这里有两个size,和aggs并列的size=0表示返回结果不包含查询结果,只返回聚合结果,terms里面的size表示返回的聚合结果数量

{

"aggs":{

"company_terms":{

"terms":{

"field":"company",

"size":2

}

}

},

"size":0

}

2.Buckets与Metric配合

POSThttp://localhost:9200/user_action/_search

将符合条件的文档按照公司进行聚合,并获取每个公司最近一次操作的时间

{

"aggs":{

"company_terms":{

"terms":{

"field":"company",

"size":2

},

"aggs":{

"latest_record":{

"max":{

"field":"timestamp"

}

}

}

}

},

"size":0

}

3.Buckets嵌套

POSThttp://localhost:9200/user_action/_search

将符合条件的文档先按照公司进行聚合,再对每个公司下的门店进行聚合,并获取每个门店最近一次操作的时间

{

"aggs":{

"company_terms":{

"terms":{

"field":"company",

"size":1

},

"aggs":{

"store_terms":{

"terms":{

"field":"store",

"size":2

},

"aggs":{

"latest_record":{

"max":{

"field":"timestamp"

}

}

}

}

}

}

},

"size":0

}

  在上面的例子中,我们使用了terms来做buckets聚合,意思是按照某个字段的值来做分组,注意这里的字段是不能做过索引的,即需要使用上面所示的.raw字段或者非string的字段。Elasticsearch提供了更多有意思的buckets聚合方法,比如常用的date_histogram,可以对时间字段按照某个间隔进行聚合,找出每个时间段内的文档数量,这对我们做基于时间序列的统计是非常有帮助的,举例如下:

POSThttp://localhost:9200/user_action/_search

{

"aggs":{

"time_histogram":{

"date_histogram":{

"field":"timestamp",

"interval":"day"

}

}

},

"size":0

}


大数据培训、人工智能培训、Python培训、大数据培训机构、大数据培训班、数据分析培训、大数据可视化培训,就选光环大数据!光环大数据,聘请专业的大数据领域知名讲师,确保教学的整体质量与教学水准。讲师团及时掌握时代潮流技术,将前沿技能融入教学中,确保学生所学知识顺应时代所需。通过深入浅出、通俗易懂的教学方式,指导学生更快的掌握技能知识,成就上万个高薪就业学子。 更多问题咨询,欢迎点击------>>>>在线客服

你可能也喜欢这些

在线客服咨询

领取资料

X
立即免费领取

请准确填写您的信息

点击领取
#第三方统计代码(模版变量) '); })();
'); })();