Elasticsearch RSETful-API的使用以及Mappings映射, 相关查询

ElasticsearchRESTFul API的简单使用

1. RSETful-API的使用

1. 索引

ES中,索引相当于MySQL中的Database

1.1 添加索引
1
2
3
4
5
6
7
8
9
PUT localhost:9200/first_index 添加新的索引, first_index
{
"settings":{
"index":{
"number_of_shards":5, 分片数
"number_of_replicas":1 副本数
}
}
}

需要注意的一点是分片数量一旦确定,不能修改.可以非常方便的在Postman工具上进行测试,上面得到返回:

1
2
3
4
5
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "first_index"
}

请求发出后可以在ES-head的web页面进行查看.

1.2 获取全部索引
1
GET localhost:9200/_all

该接口将会返回所有的索引以及索引的部分信息,这里截取一部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
"first_index": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"creation_date": "1528283704919", 创建的时间戳
"number_of_shards": "5", 分片数量,与我们创建时的一致
"number_of_replicas": "1", 副本数量
"uuid": "BcO3R1D9QcGjZc5F-UUy6g",
"version": {
"created": "6020499"
},
"provided_name": "first_index"
}
}
}

此外,ESRESTful-API设计的也非常有意思, 上面的_all接口返回了所有的索引以及索引所对应的一些信息.那么如果我只需要获取所有索引的settings信息呢?

1
GET _all/_settings

将只会返回settings信息.

1.2 获取具体索引的信息
1
2
GET first_index 获取first_index索引的全部信息
GET first_index/_settings 获取索引的settings信息
1.3 更新索引信息
1
2
3
4
PUT first_index/_settings
{
"number_of_replicas":2
}
1.4 删除索引
1
DELETE first_index
2. 数据的保存

在上面我们对索引进行了CURD的操作, 那么对数据的操作也都大同小异.

2.1 添加数据
1
2
3
4
5
6
7
8
9
10
POST first_index/type_01
{
"title":"XXXXXXXXXX",
"salary":5000,
"city":"beijing",
"cpmpany":{
"city":"",
"phone":"",
}
}

此时ES会创建该数据,并为其分配一个id:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index": "first_index",
"_type": "type_01",
"_id": "lLs72GMBEnYvYE_ZY84d",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 2
}

2.2 获取数据
1
GET first_index/type_01/{id}

2. Mappings映射

对于ES来说, Mappings就相当于关系数据库中给字段定义一个类型以及相关的属性, 能够让索引建立的更加完善和细致,提高搜索的准确率以及效率.
MySQL中字段类型可以被定义为Int, Varchar等等, 在ES中基础类型同样也是我们常见的基本数据类型.

2.1 ES中的内置数据类型
1
2
3
4
5
6
7
8
9
10
string类型:
text,keyword
text会被分析,建立反向;keyword只有在完全匹配时才会显示,不会建立倒排索引
数字类型:long,integer,short,byte,double,float
日期类型:date
bool类型:boolean
binary类型:binary
复杂类型:object, nested
geo类型(地理):geo-point,geo-shape
专业类型:ip

其中的object类型可以被看作是一个dict, nested类型可以被看做为list.
这里以一个简单的结构作为示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
PUT first_index/type_01
{
"mappings":{
"properties":{
"title":{
"type":"text"
},
"salary":{
"type":"integer"
},
"city":{
"type":"keyword"
},
"company":{
"properties":{
"name":{
"type":"text"
},
"company_addr":{
"type":"text"
},
"employee_count":{
"type":"integer"
}
}
},
"publish_date":{
"type":"date",
"format":"yyyy-MM-dd"
}
}
}
}

看着贼长,其实就是5个字段, 在company字段中继续细分了一下而已:

1
2
3
4
5
6
7
8
9
10
11
{
"title":
"salary":
"city":
"company": {
"name":
"company_addr":
"employee_count":
},
"publish_date":"2017-02-08"
}

首先推荐一波儿中文的书籍翻译, 内容比较全面:

https://github.com/elasticsearch-cn/elasticsearch-definitive-guide

整体的数据来源自一个爬虫,当然作为查询的练习来讲的话,完全可以自己随机的造一些数据,ES虽然是一个搜索引擎,但是完全可以把它当做是NoSQL来对待.

2. 数据的准备以及Mappings的建立

2.1 创建index
1
PUT localhost:9200/second_index
2.2 创建Mappings

index: second_index
type: job
字段: title, company_name, desc, publish_date

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
POST /second_index
{
"mappings":{
job type创建mappings
"job":{
"properties":{
"title":{
"store":true,
"analyzer":"ik_max_word", 使用ik分词, 可以对比ik_smart查看查询结果
"type":"text"
},
"company_name":{
"store":true,
"type":"keyword" 这里使用keyword, 表示必须精确匹配公司名称才能查询
},
"desc":{
"type":"text"
},
"publish_date":{
"type":"date",
"format":"yyyy-MM-dd"
}
}
}
}
}
2.3 数据的添加

这里用很早以前的爬虫数据来填充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
POST second_index/job
{
"title": "python爬虫开发",
"company_name": "百度",
"desc": "熟悉scrapy,熟悉redis",
"comments": 30,
"publish_date":"2017-02-08"
}

POST second_index/job
{
"title": "python工程师",
"company_name": "腾讯",
"desc": "精通python,熟悉Django/Tornado/Flask等框架",
"comments": 105,
"publish_date": "2017-05-09"
}

POST second_index/job
{
"title": "算法工程师",
"company_name": "华为",
"desc": "精通算法,硕士以上学历",
"comments": 57,
"publish_date": "2017-10-12"
}

3. 相关查询

3.1 match查询

match查询会将传入的词进行分词,拿到索引里面进行匹配,这个过程是不区分大小写的.

1
2
3
4
5
6
7
8
POST localhost:9200/second_index/job/_search
{
"query":{
"match":{
"title":"pYthOn"
}
}
}

3.2 term查询

简单来讲,term查询相当于精确查询,需要完全匹配,一个字符都不能差、不能错,这就是和match查询最大的区别

3.3 terms查询

可查询多个关键字

1
2
POST localhost:9200/second_index/job/_search
{ "query":{ "terms":{ "title":["python", "工程师"]}}}

3.4 控制返回的数量

from: 查询时显示的数量, 编写请求时与query平级即可.

3.5 指定查询返回的字段
1
2
3
4
5
6
{
"query":{
...
},
"stored_fields":["title", "company_name"]
}
3.6 指定字段进行排序
1
2
3
4
5
6
7
8
9
10
11
12
{
"query":{
"match_all":{}
},
"sort":[
{
"comments":{
"order":"desc" 对评论数进行降序排列
}
}
]
}
3.7 指定某个字段的查询范围
1
2
3
4
5
6
7
8
9
10
{
"query":{
"range":{
"comments":{
"gte":10,
"lte":50,
}
}
}
}

4. 组合查询

4.1 组合过滤

select * from job where (salary=20 OR title=python) AND (salary != 30)

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"query":{
"bool":{
"should":[
{"term":{"salary":20}},
{"term":{"title":"python"}}
],
"must_not":{
"term":{"salary":30}
}
}
}
}

常用的查询或者说搜索也就是上面的一些,当然ES中还包含有更多更复杂的查询机制, 只不过这些在日常的开发中很少用到, 遇到了再去官网的文档查看也不迟.