ElasticSearch-简介

来源:互联网 发布:焱凰赤城 知乎 编辑:程序博客网 时间:2024/06/05 16:23

Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。

Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
不过,Elasticsearch不仅仅是Lucene和全文搜索,我们还能这样去描述它:

  • 分布式的实时文件存储,每个字段都被索引并可被搜索
  • 分布式的实时分析搜索引擎
  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据

而且,所有的这些功能被集成到一个服务里面,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。

基于HTTP协议,以JSON为数据交互格式的RESTful API

其他所有程序语言都可以使用RESTful API,通过9200端口的与Elasticsearch进行通信,你可以使用你喜欢的WEB客户端,事实上,如你所见,你甚至可以通过curl命令与Elasticsearch通信。向ElasticSearch发出的请求的组成部分与其它普通的HTTP请求是一样的:

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

  • VERB:HTTP方法:GET、POST、DELETE、PUT、HEAD
  • PROTOCOL:HTTP或者HTTPS协议
  • HOST:主机名
  • PORT:ElasticSearch服务的端口,默认为9200
  • PATH:API路径,PATH可以包含多个组件,例如_cluster/stats或者_nodes/stats/jvm
  • QUERY_STRING:一些可选的请求参数,例如?pretty参数将使请求返回的更加美观易读的JSON数据
  • BODY:一个JSON格式的请求主体

举个栗子:

curl -XGET 'http://localhost:9200/_count?pretty' -d '{    "query":{        "match_all":{}    }}'

面向文档

ElasticSearch是面向文档的,这意味着它可以存储整个对象或文档。然而它不仅仅是存储,还会索引每个文档的内容使之可以被搜索。在ElasticSearch中。在ElasticSearch中,你可以对文档进行索引、搜索、排序、过滤。这种理解的方式与以往完全不同,这也是ElasticSearch能够执行复杂的全文搜索的原因之一。ElasticSearch使用JSON作为文档序列化格式,JSON现在已经被大多语言所支持,而且已经成为NoSQL领域的标准格式。它简洁、简单且容易阅读。

索引

在ElasticSearch中存储数据的行为就叫做索引(indexing),不过在索引之前,我们需要明确数据存储在哪里。在ElasticSearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中。ElasticSearch集群中可以存在多个索引(indices),每一个缩影可以包含多个类型(types),每一个类型可以包含多个文档(documents),每个文档可以包含多个字段(fields)。接下来可以看一下ElasticSearch对于与普通关系型数据库:

Relational DB --> Databases --> Tables --> Rows      --> ColumnsElasticSearch --> indices   --> types  --> documents --> fields

可以看出,ElasticSearch中索引(indices)类似于关系型数据库中的数据库,类型(types)类似于关系型数据库的表,文档(documents)类似于关系型数据库的行,字段(fields)类似于关系型数据库中的列

此时我们有个需求,往3年级2班插入一个学生的信息,我们可以通过一个命令来完成操作

curl -XPUT 'http://localhost:9200/grade3/class2/1' -d '{    "name":"张三",    "age":18,    "email":"xxx@163.com"}'

将会返回如下数据:

{  "_index" : "grade3",  "_type" : "class2",  "_id" : "1",  "_version" : 1,  "result" : "created",  "_shards" : {    "total" : 2,    "successful" : 1,    "failed" : 0  },  "created" : true}

此时就完成了一个简单的插入操作,将张三的基本信息插入到ElasticSearch中的grade3索引,class2类型中,并设Id为1。PUT请求的响应体包括{"created": true},这证实了文档已经创建了。如果我们插入ID已经存在的文档,我们仍旧会得到一个JSON响应体,但是created将会是false,表示未创建,将会将原来的文档数据覆盖。

此时我们有个需求,如果ID存在,我们就不进行插入操作,不将其覆盖,我们可以通过两种方式进行操作:
- 使用op_type查询,如:curl -XPUT "http://localhost:9200/grade3/class2/1?op_type=create"
- 在URL末端拼接_create,如:curl -XPUT "http://localhost:9200/grade3/class2/1/_create"

如果文档存在,将会出现409错误

那么我们该如何取出这个学生的信息呢,我们也可以通过一个命令来完成:

curl -XGET 'http://localhost:9200/grade3/class2/1' 

将会获得如下数据:

{    "_index": "grade3",    "_type": "class2",    "_id": "1",    "_version": 1,    "found": true,    "_source": {        "name":"张三",        "age":18,        "email":"xxx@163.com"    }}

GET 请求的响应体包括{"found": true},这证实了文档已经被找到。 如果我们请求一个不存在的文档,我们仍旧会得到一个 JSON 响应体,但是found将会是false

上面的插入方式,为开发者自己为数据设定一个ID值,当我们不需要主动设置ID值时,可以让ElasticSearch自动为你设置一个唯一个ID值,此时应该使用POST请求:

curl -XPOST 'http://localhost:9200/grade3/class2' -d '{    "name":"张三",    "age":18,    "email":"xxx@163.com"  }'

此时将会返回如下数据:

{  "_index" : "grade3",  "_type" : "class2",  "_id" : "AV8pasLoj7fgiH8Scljp",  "_version" : 1,  "result" : "created",  "_shards" : {    "total" : 2,    "successful" : 1,    "failed" : 0  },  "created" : true}

此时表明数据插入成功,并且自动为你分配一个ID:”AV8pasLoj7fgiH8Scljp”

索引命名:必须小写,不能以下划线开头,不能包含逗号。类型命名:可以是大写或小写,不能以下划线或句号开头,不能包含逗号,长度限制为256个字符

轻量搜索

一个GET是相当简单的,可以直接获得指定的文档。现在稍微尝试一下高级点的功能,比如一个简单的搜索:
- 搜索全部数据

curl -XGET 'http://localhost:9200/grade3/class2/_search'
  • 获取全部数据的数量
curl -XGET 'http://localhost:9200/grade3/class2/_count'
  • 过滤输出字段,如下值输出name与addr数据,如果什么数据都不需要,直接curl -XGET 'http://localhost:9200/grade3/class2/1?_source
curl -XGET 'http://localhost:9200/grade3/class2/1?_source=name,addr'
  • 查询名字为张三的数据
curl -XGET 'http://localhost:9200/grade3/class2/_search?q=name:张三'

值得注意的是,使用上面方法搜索中文时,如搜索name:”张三”,将匹配name中包含‘张’或者‘三’的数据,搜索英文时,如搜索name:”python developer”,将匹配name中包含‘python’或者‘developer’的数据,但英文只有一个单词的话,不会拆分成字符来搜索

根据查询表达式搜索

Query-string 搜索通过命令非常方便地进行临时性的即席搜索 ,但它有自身的局限性(参见 轻量 搜索 )。Elasticsearch 提供一个丰富灵活的查询语言叫做 查询表达式 , 它支持构建更加复杂和健壮的查询。

例如,查询name张三的数据

curl -XGET 'http://localhost:9200/grade3/class2/_search' -d '{    "query":{        "match":{            "name":"张三"        }    }}'

将会获得如下数据:

{    "took": 27,    "timed_out": false,    "_shards": {        "total": 5,        "successful": 5,        "failed": 0    },    "hits": {        "total": 6,        "max_score": 2.0519085,        "hits": [            {                "_index": "my_index",                "_type": "test_type",                "_id": "2",                "_score": 2.0519085,                "_source": {                    "name": "andoird",                    "addr": "深几把圳"                }            },            {                "_index": "my_index",                "_type": "test_type",                "_id": "4",                "_score": 0.79423964,                "_source": {                    "name": "广东",                    "addr": "深南大道"                }            }        ...        ]    }}

观察如上数据,我们可以发现有一个_score字段,即每个文档跟查询的匹配程度,ElasticSearch默认是按照_score排序的

值得注意的是,使用上面方法搜索中文时,如搜索name:”张三”,将匹配name中包含‘张’或者‘三’的数据,搜索英文时,如搜索name:”python developer”,将匹配name中包含‘python’或者‘developer’的数据,但英文只有一个单词的话,不会拆分成字符来搜索

短语搜索

找出一个属性中的独立单词是没有问题的,但有时候想要精确匹配一系列单词或者短语 。比如,我想搜索name包含张三的数据,即同时包含张和三,并且紧挨着的所有数据,很显然上面match无法实现该需求,此时需要用match_phrase

curl -XGET 'http://localhost:9200/grade3/class2/_search' -d '{    "query":{        "match_phrase":{            "name":"张三"        }    }}'

删除文档

删除文档的语法和我们所知道的规则相同,只是使用DELETE方法:

# 删除grade3索引,class2类型,id为1的数据curl -XDELETE "http://localhost:9200/grade3/class2/1"

将会获得如下数据:

{  "found" :    true,  "_index" :   "website",  "_type" :    "blog",  "_id" :      "123",  "_version" : 3}

DELETE请求体包括{"found": true},这证实了文档已经被找到并且被删除。 如果我们请求一个不存在的文档,我们仍旧会得到一个 JSON 响应体,但是found将会是false

返回数据分析

在上面的轻量搜索中知道了如何简单的搜索出数据,可是ElasticSearch通过你的搜索请求之后返回一大堆数据,是否都明白所有字段的意思呢?接下来先用一个空搜索获取到所有数据:

curl -XGET 'http://localhost:9200/grade3/class2/_search'

返回数据如下:

{  "took" : 5,  "timed_out" : false,  "_shards" : {    "total" : 15,    "successful" : 15,    "failed" : 0  },  "hits" : {    "total" : 2,    "max_score" : 1.0,    "hits" : [      {        "_index" : "grade3",        "_type" : "class2",        "_id" : "AV3p-1XqqNRvUsZQhddU",        "_score" : 1.0,        "_source" : {          "name":"张三",          "age":18,          "email":"xxx@163.com"        }      },      {        "_index" : "grade3",        "_type" : "class2",        "_id" : "123",        "_score" : 1.0,        "_source" : {          "name":"李四",          "age":20,          "email":"xxx@163.com"        }      }    ]  }}

  • hits:返回结果中,最重要的就是hits,它包含匹配到的文档的数量total,和包裹匹配到的所有数据的数组hits,以及max_score为查询锁匹配文档的_score的最大值
  • took:为整个搜索请求一共消耗了多少毫秒
  • shards:告诉我们参与查询的分片总数total,和成功了的分片数量successful,以及失败了的分片数量failed
  • timeout:是否超时,默认情况下,ElasticSearch不会超时。开发者也可以自己设置请求超时时间,如:curl -XGET 'http://localhost:9200/grade3/class2/_search?timeout=10ms'
原创粉丝点击