搜索引擎ElasticSearch命令笔记
搜索引擎ElasticSearch命令笔记
一、安装
(1)下载ES:
curl -L -O https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-版本号.tar.gz
(2)解压:
tar -xzvf elasticsearch-1.1.1.tar.gz -C 保存目录
(3)修改ES的文件权限为777:
chmod 777 elasticsearch-version -R
(4)启动ES
进入ES源码目录,启动ES:
./bin/elasticsearch
如果想在后台以守护进程模式运行,添加-d参数。
我们可以覆盖集群或者节点的名字。我们可以在启动Elasticsearch的时候通过命令行来指定,如下:
./elasticsearch --cluster.name my_cluster_name --node.name my_node_name
(5)打开另一个终端进行测试:
curl 'http://localhost:9200/?pretty'
注意一下有http标记的那一行,它提供了有关HTTP地址(127.0.0.1)和端口(9200)的信息,通过这个地址和端口我们就可以访问我们的节点了。默认情况下,Elasticsearch使用9200来提供对其REST API的访问。如果有必要,这个端口是可以配置的。
查看状态:http://{es-host}:9200| netstat –ano|grep 9300
(6)关闭ES:
当Elasticsearch在前台运行,可以使用Ctrl-C快捷键终止,或者你可以调用shutdown API来关闭:
curl -XPOST 'http://localhost:9200/_shutdown'
二、RESTful API
所有程序语言都可以使用基于HTTP协议,以JSON为数据交互格式的RESTful API,通过9200端口与Elasticsearch进行通信。
1、发送请求
向Elasticsearch发出的请求的组成部分与其它普通的HTTP请求是一样的:
curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'
参数含义:
1)VERB HTTP方法:GET, POST, PUT, HEAD, DELETE
2)PROTOCOL http或者https协议(只有在Elasticsearch前面有https代理的时候可用)
3)HOST Elasticsearch集群中的任何一个节点的主机名,如果是在本地的节点,那么就叫localhost
4)PORT Elasticsearch HTTP服务所在的端口,默认为9200
5)PATH API路径(例如_count将返回集群中文档的数量),PATH可以包含多个组件,例如_cluster/stats或者_nodes/stats/jvm
6)QUERY_STRING 一些可选的查询请求参数,例如?pretty参数将使请求返回更加美观易读的JSON数据
7)BODY 一个JSON格式的请求主体(如果请求需要的话)
2、功能
通过RESTful API,你可以:
1)检查你的集群、节点和索引的健康状态、和各种统计信息
2)管理你的集群、节点、索引数据和元数据
3)对你的索引进行CRUD(创建、读取、更新和删除)和搜索操作
4)执行高级的查询操作,像是分页、排序、过滤、脚本编写(scripting)、小平面刻画(faceting)、聚合(aggregations)和许多其它操作
3、集群健康
使用_cat API检查集群健康:
curl -XGET 'localhost:9200/_cat/health?v&pretty'
当我们询问集群状态的时候,我们要么得到绿色、黄色或红色。绿色代表一切正常(集群功能齐全),黄色意味着所有的数据都是可用的,但是某些复制没有被分配(集群功能齐全),红色则代表因为某些原因,某些数据不可用。注意,即使是集群状态是红色的,集群仍然是部分可用的(它仍然会利用可用的分片来响应搜索请求),但是可能你需要尽快修复它,因为你有丢失的数据。
4、列举节点、索引
curl 'localhost:9200/_cat/nodes?v'
curl 'localhost:9200/_cat/indices?v'
curl -XGET 'localhost:9200/_cat/indices?v&pretty'
5、创建一个索引
curl -XPUT 'localhost:9200/customer?pretty'
默认会有5个分片 1个索引
在Elasticsearch中,文档归属于一种类型(type),而这些类型存在于索引(index)中,我们可以画一些简单的对比图来类比传统关系型数据库:
Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices -> Types -> Documents -> Fields
6、删除一个索引
curl -XDELETE 'localhost:9200/customer?pretty'
7、索引并查询一个文档
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
"name": "John Doe"
}'
为了索引一个文档,我们必须告诉Elasticsearch这个文档要到这个索引的哪个类型(type)下。我们将一个简单的客户文档索引到customer索引、“external”类型中,这个文档的ID是1,这个id是我们在索引的时候指定的。
注意,Elasticsearch在你想将文档索引到某个索引的时候,并不强制要求这个索引被显式地创建。如果customer索引不存在,Elasticsearch将会自动地创建这个索引。
把刚刚索引的文档取出来:
curl -XGET 'localhost:9200/customer/external/1?pretty'
除了一个叫做found的字段来指明我们找到了一个ID为1的文档,和另外一个字段——_source——返回我们前一步中索引的完整JSON文档之外,其它的都没有什么特别之处。
8、修改数据(索引/替换文档)
我们先前看到,怎样索引一个文档。现在我们再次调用那个命令:
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
"name": "John Doe"
}'
以上的命令将会把这个文档索引到customer索引、external类型中,其ID是1。
如果我们对一个不同(或相同)的文档应用以上的命令,Elasticsearch将会用一个新的文档来替换(重新索引)当前ID为1的那个文档。
curl -XPUT 'localhost:9200/customer/external/1?pretty' -d '
{
"name": "Jane Doe"
}'
以上的命令将ID为1的文档的name字段的值从“John Doe”改成了“Jane Doe”。
如果我们使用一个不同的ID,一个新的文档将会被索引,当前已经在索引中的文档不会受到影响。
curl -XPUT 'localhost:9200/customer/external/2?pretty' -d '
{
"name": "Jane Doe"
}'
以上的命令,将会索引一个ID为2的新文档。
在索引的时候,ID部分是可选的。如果不指定,Elasticsearch将产生一个随机的ID来索引这个文档。Elasticsearch生成的ID会作为索引API调用的一部分被返回。
以下的例子展示了怎样在没有指定ID的情况下来索引一个文档:
curl -XPOST 'localhost:9200/customer/external?pretty' -d '
{
"name": "Jane Doe"
}'
注意,在上面的情形中,由于我们没有指定一个ID,我们使用的是POST而不是PUT。
9、更新文档
注意,Elasticsearch底层并不支持原地更新。在我们想要做一次更新的时候,Elasticsearch先删除旧文档,然后再索引一个更新过的新文档。
将ID为1的文档的name字段改成“Jane Doe”:
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
"doc": { "name": "Jane Doe" }
}'
将ID为1的文档的name字段改成“Jane Doe”的同时,给它加上age字段:
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
"doc": { "name": "Jane Doe", "age": 20 }
}'
更新也可以通过使用简单的脚本来进行。使用一个脚本将age加5:
curl -XPOST 'localhost:9200/customer/external/1/_update?pretty' -d '
{
"script" : "ctx._source.age += 5"
}'
在上面的例子中,ctx._source指向当前要被更新的文档。
注意,在写作本文时,更新操作只能一次应用在一个文档上。将来,Elasticsearch将提供同时更新符合指定查询条件的多个文档的功能(类似于SQL的UPDATE-WHERE语句)。
10、删除文档
删除ID为2的文档:
curl -XDELETE 'localhost:9200/customer/external/2?pretty'
我们也能够一次删除符合某个查询条件的多个文档。以下的例子展示了如何删除名字中包含“John”的所有的客户:
curl -XDELETE 'localhost:9200/customer/external/_query?pretty' -d '
{
"query": { "match": { "name": "John" } }
}'
注意,以上的URI变成了/_query
,以此来表明这是一个“查询删除”API,其中删除查询标准放在请求体中,但是我们仍然使用DELETE。
11、批处理
除了能够对单个的文档进行索引、更新和删除之外,Elasticsearch也提供了以上操作的批量处理功能,这是通过使用_bulk API实现的。这个功能之所以重要,在于它提供了非常高效的机制来尽可能快的完成多个操作,与此同时使用尽可能少的网络往返。
作为一个快速的例子,以下调用在一次bulk操作中索引了两个文档(ID 1 - John Doe and ID 2 - Jane Doe):
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }
'
以下例子在一个bulk操作中,首先更新第一个文档(ID为1),然后删除第二个文档(ID为2):
curl -XPOST 'localhost:9200/customer/external/_bulk?pretty' -d '
{"update":{"_id":"1"}}
{"doc": { "name": "John Doe becomes Jane Doe" } }
{"delete":{"_id":"2"}}
'
注意上面的delete动作,由于删除动作只需要被删除文档的ID,所以并没有对应的源文档。
bulk API按顺序执行这些动作。如果其中一个动作因为某些原因失败了,将会继续处理它后面的动作。当bulk API返回时,它将提供每个动作的状态(按照同样的顺序),所以你能够看到某个动作成功与否。
三、探索数据
1、样本数据集JSON格式
Elasticsearch是面向文档(document oriented)的,这意味着它可以存储整个对象或文档(document)。然而它不仅仅是存储,还会索引(index)每个文档的内容使之可以被搜索。在Elasticsearch中,你可以对文档(而非成行成列的数据)进行索引、搜索、排序、过滤。这种理解数据的方式与以往完全不同,这也是Elasticsearch能够执行复杂的全文搜索的原因之一。
ELasticsearch使用Javascript对象符号(JavaScript Object Notation),也就是JSON,作为文档序列化格式。
使用JSON文档来表示一个客户的银行账户信息:
{
"account_number": 0,
"balance": 16623,
"firstname": "Bradshaw",
"lastname": "Mckenzie",
"age": 29,
"gender": "F",
"address": "244 Columbus Place",
"employer": "Euron",
"email": "bradshawmckenzie@euron.com",
"city": "Hobucken",
"state": "CO"
}
2、 载入样本数据
curl -XPOST 'localhost:9200/bank/account/_bulk?pretty' --data-binary @accounts.json
3、 搜索API
有两种基本的方式来运行搜索:一种是在REST请求的URI中发送搜索参数,另一种是将搜索参数发送到REST请求体中。请求体方法的表达能力更好,并且你可以使用更加可读的JSON格式来定义搜索。
搜索的REST API可以通过_search端点来访问。下面这个例子返回bank索引中的所有的文档:
curl 'localhost:9200/bank/_search?q=*&pretty'
curl -XGET 'localhost:9200/bank/_search?q=*&sort=account_number:asc&pretty'
我们在bank索引中搜索(_search端点),并且q=*参数指示Elasticsearch去匹配这个索引中所有的文档。
对于这个响应,我们看到了以下的部分:
- took —— Elasticsearch执行这个搜索的耗时,以毫秒为单位
- timed_out —— 指明这个搜索是否超时
- _shards —— 指出多少个分片被搜索了,同时也指出了成功/失败的被搜索的shards的数量
- hits —— 搜索结果
- hits.total —— 能够匹配我们查询标准的文档的总数目
- hits.hits —— 真正的搜索结果数据(默认只显示前10个文档)
- _score和max_score —— 现在先忽略这些字段
使用请求体方法的等价搜索是:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_all": {} }
}'
curl -XGET 'localhost:9200/bank/_search?pretty' -d'
{
"query": { "match_all": {} },
"sort": [
{ "account_number": "asc" }
]
}'
这里的不同之处在于,并不是向URI中传递q=*
,取而代之的是,我们在_search API的请求体中POST了一个JSON格式请求体。
注意:一旦你取回了你的搜索结果,Elasticsearch就完成了使命,它不会维护任何服务器端的资源或者在你的结果中打开游标。
4、查询语言(查询DSL)
DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。
1)查询匹配所有,但是只查询一个
curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match_all": {} }, "size": 1}'
注意:如果没有指定大小 默认返回10
2)从11位开始查询10个
curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match_all": {} }, "from": 10, "size": 10}'
未指定from的话,默认是 0
3)查询所有,按照 balance 排序
curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match_all": {} }, "sort": { "balance": { "order": "desc" } }}'
4)查询所有数据,但是只获取指定字段
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_all": {} },
"_source": ["account_number", "balance"],
"size": 1
}'
5)查询 account_method = 20
curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match": { "account_number": 20 } }}'
6)查询地址里包含 mill的
curl-XPOST'localhost:9200/bank/_search?pretty'-d'{ "query": { "match": { "address": "mill" } }}'
7)返回地址中包含“mill”或者包含“lane”的账户:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match": { "address": "mill lane" } }
}'
8)下面这个例子是match的变体(match_phrase),它会去匹配短语“mill lane”:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": { "match_phrase": { "address": "mill lane" } }
}'
9)布尔查询
布尔查询允许我们利用布尔逻辑将较小的查询组合成较大的查询。
a) 这个例子组合了两个match查询,这个组合查询返回包含“mill”和“lane”的所有的账户:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
bool must语句指明了,对于一个文档,所有的查询都必须为真,这个文档才能够匹配成功。
b) 查询2个条件 只要有一个满足就返回
下面的例子组合了两个match查询,它返回的是地址中包含“mill”或者“lane”的所有的账户:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"should": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
bool should语句指明,对于一个文档,查询列表中,只要有一个查询匹配,那么这个文档就被看成是匹配的。
c) 不包括下面2个搜索项的数据查询
这个例子组合了两个查询,它返回地址中既不包含“mill”,同时也不包含“lane”的所有的账户信息:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must_not": [
{ "match": { "address": "mill" } },
{ "match": { "address": "lane" } }
]
}
}
}'
bool must_not语句指明,对于一个文档,查询列表中的的所有查询都必须都不为真,这个文档才被认为是匹配的。
d) 多种状态一起查询
我们可以在一个bool查询里一起使用must、should、must_not。此外,我们可以将bool查询放到这样的bool语句中来模拟复杂的、多等级的布尔逻辑。
下面这个例子返回40岁以上并且不生活在ID(daho)的人的账户:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"bool": {
"must": [
{ "match": { "age": "40" } }
],
"must_not": [
{ "match": { "state": "ID" } }
]
}
}
}'
10) 过滤器
搜索结果中的_score字段表示文档的得分,这个得分是与我们指定的搜索查询匹配程度的一个相对度量。得分越高,文档越相关,得分越低,文档的相关度越低。
Elasticsearch中的所有的查询都会触发相关度得分的计算。对于那些我们不需要相关度得分的场景下,Elasticsearch以过滤器的形式提供了另一种查询功能。过滤器在概念上类似于查询,但是它们有非常快的执行速度,这种快的执行速度主要有以下两个原因:
- 过滤器不会计算相关度的得分,所以它们在计算上更快一些
- 过滤器可以被缓存到内存中,这使得在重复的搜索查询上,其要比相应的查询快出许多。
这个例子使用一个被过滤的查询,其返回值是资金在20000到30000之间(闭区间)的账户。
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"query": {
"filtered": {
"query": { "match_all": {} },
"filter": {
"range": {
"balance": {
"gte": 20000,
"lte": 30000
}
}
}
}
}
}'
通常情况下,要决定是使用过滤器还是使用查询,取决于是否需要相关度得分。如果相关度是不重要的,使用过滤器,否则使用查询。
11) 聚合
聚合提供了分组并统计数据的能力。理解聚合的最简单的方式是将其粗略地等同为SQL的GROUP BY和SQL聚合函数。在Elasticsearch中,你可以在一个响应中同时返回命中的数据和聚合结果。你可以使用简单的API同时运行查询和多个聚合,并以一次返回,这避免了来回的网络通信,这是非常强大和高效的。
a)按照state分组,按照州名的计数倒序排序:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state"
}
}
}
}'
注意我们将size设置成0,这样我们就可以只看到聚合结果了,而不会显示命中的结果。
b) 在先前聚合的基础上,现在这个例子计算了每个州的账户的平均余额(还是按照账户数量倒序排序的前10个州):
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}'
注意,我们把average_balance聚合嵌套在了group_by_state聚合之中。这是所有聚合的一个常用模式。你可以任意的聚合之中嵌套聚合,这样你就可以从你的数据中抽取出想要的概述。
c) 基于前面的聚合,现在让我们按照平均余额进行排序:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_state": {
"terms": {
"field": "state",
"order": {
"average_balance": "desc"
}
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}'
d) 下面的例子显示了如何使用年龄段(20-29,30-39,40-49)分组,然后在用性别分组,然后为每一个年龄段的每一个性别计算平均账户余额:
curl -XPOST 'localhost:9200/bank/_search?pretty' -d '
{
"size": 0,
"aggs": {
"group_by_age": {
"range": {
"field": "age",
"ranges": [
{
"from": 20,
"to": 30
},
{
"from": 30,
"to": 40
},
{
"from": 40,
"to": 50
}
]
},
"aggs": {
"group_by_gender": {
"terms": {
"field": "gender"
},
"aggs": {
"average_balance": {
"avg": {
"field": "balance"
}
}
}
}
}
}
}
}'
12) 高亮
GET /megacorp/employee/_search
{
"query" : {
"match_phrase" : {
"about" : "rock climbing"
}
},
"highlight": {
"fields" : {
"about" : {}
}
}
}
当我们运行这个语句时,会命中与之前相同的结果,但是在返回结果中会有一个新的部分叫做highlight,这里包含了来自about字段中的文本,并且用<em></em>
来标识匹配到的单词。
13)分词
http://localhost:9200/_analyze?pretty&analyzer=index_ansj&text=%E5%85%AD%E5%91%B3%E5%9C%B0%E9%BB%84%E4%B8%B8%E8%BD%AF%E8%83%B6%E5%9B%8A
还没有评论,来说两句吧...