IT技术干货栏——分享移动端&前端&后端编程从入门到高级玩转大数据程序员

Elasticsearch入门(1)

2017-04-09  本文已影响242人  iszhenyu

很多东西在工作中一直使用,但是从来没有认真总结过,遇到问题了就上网翻翻文档,工作中的问题是解决了,但是回过头去看,又好像什么都不懂,只是对经常使用的知识比较熟悉而已。这也是这篇文章产生的原因,希望通过这种方式,让自己的知识更加系统化。好了,下面就来说说ElasticSearch,这篇文章偏入门些,如果您已经对ElasticSearch非常熟悉了,当然也可以再浏览下,如果你还从来没接触过,希望这篇文章可以帮助到你。

我们下面的讲解与实例都是基于5.2版本的,由于ElasticSearch之前的版本跟目前这个版本有一定的差别,所以如果当你对照例子发现无法运行时,那么最可能的原因就是版本的问题了。

Elasticsearch是一个基于Lucene的开源搜索引擎,而Lucene本身是非常复杂的,要想直接使用Lucene并不是太容易。Elasticsearch的出现就是希望通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。

ES的安装

ES的安装是非常简单的,唯一需要我们配置的就是java环境,5.2的版本需要java8的支持,所以首先确保本地已经安装了java8或以上版本。接下来下载对应的二进制包,如果是mac或linux系统可以直接通过curl来下载

curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.2.2.tar.gz

对下载好的压缩包进行解压处理

tar -xvf elasticsearch-5.2.2.tar.gz

然后进入到解压后的elasticsearch-5.2.2/bin目录中,直接运行elasticsearch

bin ./elasticsearch

之后,新打开一个终端窗口,执行如下的命令:

curl 'http://localhost:9200/?pretty'

如果启动成功,我们会看到类似下面的响应信息:

{
  "name" : "EF-dAP-",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "4KsT9m6iRfqUfafnsklDcw",
  "version" : {
    "number" : "5.2.2",
    "build_hash" : "f9d9b74",
    "build_date" : "2017-02-24T17:26:45.835Z",
    "build_snapshot" : false,
    "lucene_version" : "6.4.1"
  },
  "tagline" : "You Know, for Search"
}

ES的几个概念

在ES中,数据都是按照JSON格式存储的,比如下面的例子

"email": "lisi@qq.com",
"first_name": "li",
"last_name": "si",
"info": {
    "age": 25,
    "interests": [ "dolphins", "whales" ]
},
"join_date": "2017/04/06"

它描述了一个user对象,同时,在ES中它也代表了一个文档。ES在对这个文档进行存储的同时,还会对文档中的内容进行倒排索引,以便于后续的查找、过滤、排序等操作。

在关系型数据库中,我们熟悉的是databasetablerowcolumn等概念,同样,在ES中也存在着类似的定义。

在ES中,索引(index)指的是具有相同属性的文档的集合,每个索引(index)包含多个类型(type),每个类型又包含多个文档(document),每个文档包含了多个字段(field)。如果跟关系型数据库的结构对照的话,大致可以如下表示:

Elasticsearch 关系型数据库
Index Database
Type Table
Document Row
Field Column

在ES中,索引是一个非常重要的概念,不同的场景下代表了不同的含义。这里有必要对在ES中使用的索引一词做一下澄清。

传统的关系型数据库中,索引代表对数据库中的一列或多列的值进行排序的一种存储结构,利用索引可以快速获得所需的内容。

而在ES中,索引作为名词来讲表示的是一个存储了相关文档的集合,可以对比于关系型数据库中的database。当我们在ES中保存数据时,也称为对其进行索引处理,这里按动词理解,可以对比于关系型数据库中的insert操作。

Elasticsearch能够对全文本进行快速的搜索,得益于其实用的一种数据结构:倒排索引(Inverted Index)。在倒排索引中,包含一个在所有文档中出现的字词的列表,其中,每一个字词又对应一个列表,这个列表的内容就是所有包含这个字词的文档。当搜索时,首先会对我们搜索的内容进行分词处理,然后检查每个分好的词对应哪些文档,最后汇总给我们结果。

ES常用操作

ES提供了非常丰富和强大的REST API,通过这些API我们可以检查集群、节点和索引的健康情况,并对它们进行管理,可以在索引上对数据进行增删改查,更可以执行类似分页、排序、过滤、聚合等这样的高级查询操作。

对集群、节点和索引的操作

curl -XGET 'localhost:9200/_cat/health?v&pretty'

在返回的结果中,包含一个status字段,它的取值有三种,分别是greenyellowredgreen意味着一切正常,yellow意味着数据是可用的,但是一些备份数据还没准备好,最后red意味某些数据是不可用的,尽管如此,但部分功能还是可用的,只不过你需要尽快去处理。

curl -XGET 'localhost:9200/_cat/nodes?v&pretty'
curl -XGET 'localhost:9200/_cat/indices?v&pretty'
curl -XPUT 'localhost:9200/customer?pretty&pretty'
curl -XDELETE 'localhost:9200/customer?pretty&pretty'
curl -XPUT 'localhost:9200/xx_questions_v1/_alias/xx_questions'
curl -XGET 'localhost:9200/_alias/xx_questions?pretty'
// or
curl -XGET 'localhost:9200/_alias/xx_questions*?pretty'
curl -XGET 'localhost:9200/xx_questions_v1/_alias?pretty'
curl -XDELETE 'localhost:9200/xx_questions_v1/_alias/xx_questions'
curl -XPOST 'http://localhost:9200/_aliases' -d '
{
    "actions" : [
        { "remove" : { "index" : "dm_v1", "alias" : "dm" } },
        { "add" : { "index" : "dm_v2", "alias" : "dm" } }
    ]
}'
curl -XPUT 'http://localhost:9200/task_es/_settings' -H 'Content-Type:appliation' -d '{
    "index": {
        "refresh_interval": "30s",
        "number_of_replicas": 1
    }
}'
curl -XPOST 'http://localhost:9200/{index}/_mapping?pretty=true' -H 'Content-Type:application/json' -d '{
    // mapping
}'

索引上的增删改查

首先,在customer索引上新增一个文档

curl -XPUT 'localhost:9200/customer/external/1?pretty&pretty' -H 'Content-Type: application/json' -d'
{
  "first_name": "zhang", "last_name":"si"
}
'

上面的语句执行完毕后,会在customer索引中的external类型中新加入一个ID为1的文档。我们可以通过ID来访问这个新加入的文档:

curl -XGET 'localhost:9200/customer/external/1?pretty&pretty'

它的结果应该像下面这样,除了一个found字段,就没啥特别的了

{
  "_index" : "customer",
  "_type" : "external",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : { "first_name": "zhang", "last_name": "si"}
}

这里要说明的是,Elasticsearch中对数据进行操作后,并不是立即就能够搜索的,这中间会有大概1秒钟的延迟。

现在,假如我们想将这个ID为1的文档替换成其他的文档,比如换成名字为lisi的文档,则只需要再执行一次上面的put操作即可,ID还是指定为1:

curl -XPUT 'localhost:9200/customer/external/1?pretty&pretty' -H 'Content-Type: application/json' -d'
{
  "first_name": "li", "last_name":"si"
}
'

再次获取ID为1的文档,我们发现名称已经变成了lisi。假如说我们在执行替换的时候指定的ID不是1,比如是2,会怎样呢?

curl -XPUT 'localhost:9200/customer/external/2?pretty&pretty' -H 'Content-Type: application/json' -d'
{
  "first_name": "wang", "last_name": "wu"
}
'

这句话执行的结果就是索引了一个新的文档,新文档的ID是2。

可以看到,ES跟传统关系型数据库是不同的,在传统关系型数据库中,如果库中已经有一个ID是1的数据(这里ID作为主键)则再执行插入为1的操作会报错。而在ES中,通过PUT可以来进行createupdate这两种操作,我们可以这样理解:当ES中已经存在特定的ID时,会执行更新操作,当ES中没有这个ID时会执行插入操作。

在ES内部,其实并不是真正的去更新文档,而是先删除旧的文档,再重新索引这个新的文档。所以,也就不难理解为什么上面的两个PUT操作会有不同的效果了。

除了索引文档的时候可以指定ID外,也可以不指定,如果不指定ID,ES会生成一个随机的ID,同时,必须使用POST方法来索引一个文档:

curl -XPOST 'localhost:9200/customer/external?pretty&pretty' -H 'Content-Type: application/json' -d'
{
  "first_name": "zhao", "last_name": "liu"
}
'

对于更新操作,有的时候我们并不想更新整个文档,而只是想更新文档中的某个字段,怎么操作呢?我们还以上面为例,假如只想改变first_name字段,名字改成zhang lisi:

curl -XPOST 'localhost:9200/customer/external/1/_update?pretty&pretty' -H 'Content-Type: application/json' -d'
{
  "doc": { "first_name": "zhang" }
}
'

与上面替换整个文档不同的是,我们这里使用的是POST操作,同时在url中指定了是_update,并且,将要更新的内容嵌套在了doc字段中。通过这个操作,我们不但可以更新已有的字段,也可以新增字段,比如,下面的操作会新增一个age字段:

curl -XPOST 'localhost:9200/customer/external/1/_update?pretty&pretty' -H 'Content-Type: application/json' -d'
{
  "doc": { "first_name": "zhang", "age": 25 }
}
'

根据RESTful API规范,我们不难推断出来,删除一个文档只要使用DELETE句可以了:

curl -XDELETE 'localhost:9200/customer/external/2?pretty&pretty'

我们上面的操作都是基于单个文档的,ES同样提供了批量操作的接口。使用批量操作也很简单,首先在URL上通过_bulk告诉ES我们使用的是批量操作,其次,对于每个数据,我们还要告诉ES是什么类型的操作,比如下面的例子:

curl -XPOST 'localhost:9200/customer/external/_bulk?pretty&pretty' -H 'Content-Type: application/json' -d'
{"index":{"_id":"1"}}
{"first_name": "zhang", "last_name": "san"}
{"index":{"_id":"2"}}
{"first_name": "li", "last_name": "si"}
'

{"index":{"_id":"1"}}告诉ES是要新索引一个文档,文档的ID是1,紧跟着的{"first_name": "zhang", "last_name": "san"}是这个ID为1的文档的内容,同理,我们也可以在一次批处理中同时包含更新和删除操作:

curl -XPOST 'localhost:9200/customer/external/_bulk?pretty&pretty' -H 'Content-Type: application/json' -d'
{"update":{"_id":"1"}}
{"doc": { "last_name": "san si wu" } }
{"delete":{"_id":"2"}}
'

上面的操作会首先更新ID为1的文档的last_name字段,然后删除ID为2的文档。

在入门(1)中,主要就是介绍一下ES的基本的概念和一些基本的操作,在入门(2)中会继续介绍ES中的高级查询。


这样学机器学习
上一篇下一篇

猜你喜欢

热点阅读