Elasticsearch学习笔记(二)

我们可以简单地认为在Elasticsearch中存储的数据是JSON格式的,或者理解成存储在mongo数据库中。Elasticsearch中有四个基本概念,Indices(索引),Types(类型),Documents(文档)和Fields(字段),索引相当于关系型数据库中的数据库,类型相当于表,文档相当于行,字段相当于列。

既然我们已经知道了操作Elasticsearch相当于操作一个Restful的服务,那么就很简单了。

我们用《Elasticsearch权威指南》中的例子来说明。

PUT

插入一条员工记录:

1
2
3
4
5
6
7
8
curl -XPUT 'http://localhost:9200/megacorp/emplyee/1' -d '
{
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [ "sports", "music" ]
}'

PATH为/megacorp/emplyee/1,包含三部分信息,megacorp是索引名,emplyee是类型名,1是员工id。

我们在插入一条记录的时候需要为记录指定id,如果不指定的话会出现错误No handler found for uri...。id也可以用字符串。

返回信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"_index" : "megacorp",
"_type" : "emplyee",
"_id" : "1",
"_version" : 1,
"_shards" :
{
"total" : 2,
"successful" : 2,
"failed" : 0
},
"created" : true # 返回true表示文档新创建,false表示更新
}

如果操作的索引和类型不存在,Elasticsearch会自动创建索引和类型,不需要手动操作,如果存在的话就更新相应的字段。PUT操作时,如果对应id的员工不存在,则新建,如果存在,则更新。

关于更新需要注意的是,更新操作会清除现有的数据,然后将你新提交的新数据插入。我只想更新一个字段,如果在提交的JSON只包含这个字段的信息,那么恭喜你,其他字段的数据被销毁了。你可能想到把不用更新的字段也加入的JSON中,没错这样的确可以,但是太麻烦,后面的笔记会介绍怎么用_update解决这个问题。

用POST操作和用PUT一样,但是两者还是有区别的,后面会说。

GET

我们通过GET进行数据查询:

1
2
# pretty为了让输出更好看
curl -XGET 'http://localhost:9200/megacorp/emplyee/1/?pretty'

返回信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index" : "megacorp",
"_type" : "emplyee",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [ "sports", "music" ]
}
}

我只需要first_namelast_name两个字段:

1
curl -XGET "http://localhost:9200/megacorp/emplyee/1/?pretty&_source=first_name,last_name"

1
2
3
4
5
6
7
8
9
10
11
{
"_index": "megacorp",
"_type": "emplyee",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"last_name": "Smith",
"first_name": "John"
}
}

我只想获得源数据(_source),不需要_index_type等信息:

1
curl -XGET "http://localhost:9200/megacorp/emplyee/1/_source?pretty"

1
2
3
4
5
6
7
8
9
10
{
"first_name": "John",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [
"sports",
"music"
]
}

我们通过HEAD检查文档是否存在:

1
curl -XHEADER 'http://localhost:9200/megacorp/emplyee/1/?pretty'

返回信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"_index" : "megacorp",
"_type" : "emplyee",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"first_name" : "John",
"last_name" : "Smith",
"age" : 25,
"about" : "I love to go rock climbing",
"interests" : [ "sports", "music" ]
}
}

注意是HEADER不是HEAD,如果文档存在,返回信息和GET方法一样,如果不存在,返回信息如下:

1
2
3
4
5
6
{
"_index" : "megacorp",
"_type" : "emplyee",
"_id" : "1",
"found" : false
}

DELETE

1
curl -XDELETE 'http://localhost:9200/megacorp/emplyee/1/?pretty'

返回信息:

1
2
3
4
5
6
7
8
9
10
11
12
{
"found" : true,
"_index" : "megacorp",
"_type" : "emplyee",
"_id" : "1",
"_version" : 1,
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
}
}

简单查询

搜索全部员工信息:

1
curl -XGET "localhost:9200/megacorp/emplyee/_search/?pretty"

默认返回10条记录。

搜索姓氏中包含”Smith”的员工:

1
curl -XGET "localhost:9200/megacorp/emplyee/_search/?q=last_name:Smith&pretty"

使用DSL语言查询

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# 搜索姓氏中包含"Smith"的员工
curl -XGET "localhost:9200/megacorp/emplyee/_search" -d '
{
"query": {
"match": {
"last_name": "Smith"
}
}
}'
# 搜搜姓氏包含"Smith"且年龄大于30岁的员工
curl -XGET "http://localhost:9200/_search/?pretty" -d'
{
"query": {
"filtered": {
"filter": {
"range": {
"age": {"gt": 20}
}
},
"query": {
"match": {
"last_name": "Smith"
}
}
}
}
}'
# 全文搜索
curl -XGET "http://localhost:9200/_search" -d'
{
"query": {
"match": {
"about": "rock"
}
}
}'
# 全文搜索返回信息
{
"took": 29,
"timed_out": false,
"_shards": {
"total": 7,
"successful": 7,
"failed": 0
},
"hits": {
"total": 11,
"max_score": 0.42292467,
"hits": [
...
{
"_index": "megacorp",
"_type": "emplyee",
"_id": "100",
"_score": 0.42292467,
"_source": {
"first_name": "Jack",
"last_name": "Spark",
"age": 20,
"about": "I love rock",
"interests": [
"sports",
"music"
]
}
},
{
"_index": "megacorp",
"_type": "emplyee",
"_id": "104173113",
"_score": 0.3171935,
"_source": {
"first_name": "Johnk",
"last_name": "Smith",
"age": 25,
"about": "I love to go rock climbing",
"interests": [
"sports",
"music"
]
}
}]
}
}

在简单查询中,我们使用?q=last_name:Smith的方式查询,简单的查询任务没什么问题,但是这种方式太局限,官方提供了一种灵活的查询语言DSL(Domain Specific Language特定领域语言)。DSL以JSON请求体的形式出现。

我们看全文搜索的返回信息,有一个_score的字段,表示相关性的评分,还有一个max_score表示最高得分,emplyee表中about字段中包含的信息和rock越相似,评分越高。在进行前两条的DSL查询的时候,返回的结果中也包含max_score_score,ElasticSearch中的查询,有点像sql中的like

默认情况下,按评分从高到低排序,所谓相关性评分就是文档与查询条件的匹配程度。

本文简单的介绍了对Elasticsearch的操作,你会发现讲解的部分不多,因为Restful的方式特别简洁明了。

我在实际进行操作的过程中发现,用JSON作为查询体的方式太容易出错,然后发现了一个chrome的插件可以帮住我们,A JSON aware developer console to ElasticSearch

􏴑