Elasticsearch 提供了 REST API,操作起来很方便。上一篇已经在 CentOS 7 上安装了 Elasticsearch 5.6.2 和 IK 中文分词器,这次继续用 curl 完成索引、文档和搜索的基本操作。
Elasticsearch 仍然只允许内网访问,不要把 9200 端口直接暴露到公网。本文只介绍单机操作,不涉及集群内容。
基本概念
刚接触 Elasticsearch 时,index、type、document 和 field 这些概念容易混淆。可以先和 MySQL 粗略对照:
| Elasticsearch | MySQL 中接近的概念 |
|---|---|
| Index | Database 或 Table |
| Type | Table |
| Document | Row |
| Field | Column |
| Mapping | Schema |
这个对照只方便理解,二者并不是一一对应。特别是同一索引下不同 type 的同名字段会共用底层 Lucene 字段,不能像 MySQL 中彼此独立的表那样看待。
Type 会在后续版本中逐步移除。Elasticsearch 5.6 还支持 type,但一个索引最好只存放一种结构的文档。具体原因可以参考 Elastic 的 Indices, types, and parent / child。
创建索引
创建名为 specs 的索引和名为 spec 的 type,并为 factory、name 两个字段设置 IK 分词器。索引名称必须使用小写字母:
curl -X PUT 'http://localhost:9200/specs' \
-H 'Content-Type: application/json' \
-d '{
"mappings": {
"spec": {
"properties": {
"factory": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"name": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
}
}
}
}'创建成功会返回:
{
"acknowledged": true,
"shards_acknowledged": true,
"index": "specs"
}查看 mapping:
curl 'http://localhost:9200/specs/_mapping?pretty'可以看到 spec 下的两个字段及对应分词器:
{
"specs": {
"mappings": {
"spec": {
"properties": {
"factory": {
"type": "text",
"analyzer": "ik_max_word"
},
"name": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
}
}如果需要删除整个示例索引,可以执行:
curl -X DELETE 'http://localhost:9200/specs'删除索引会同时删除其中的 mapping 和全部文档,下面还要继续操作数据,先不要执行这条命令。
操作文档
写入文档
向 specs 索引的 spec type 写入第一条车型数据,并指定文档 ID 为 1:
curl -X PUT 'http://localhost:9200/specs/spec/1?pretty' \
-H 'Content-Type: application/json' \
-d '{
"factory": "一汽-大众奥迪",
"name": "奥迪A6L 2018款 30周年年型 TFSI 进取型"
}'返回结果中的 result 为 created,说明文档创建成功:
{
"_index": "specs",
"_type": "spec",
"_id": "1",
"_version": 1,
"result": "created"
}specs 是索引,spec 是 type,1 是指定的文档 ID。ID 不一定是数字,也可以使用字符串;如果不指定 ID,需要改用 POST /specs/spec,由 Elasticsearch 自动生成。
再写入两条数据:
curl -X PUT 'http://localhost:9200/specs/spec/2' \
-H 'Content-Type: application/json' \
-d '{
"factory": "上汽大众",
"name": "途观L 2017款 330TSI 自动两驱豪华版"
}'
curl -X PUT 'http://localhost:9200/specs/spec/3' \
-H 'Content-Type: application/json' \
-d '{
"factory": "一汽-大众奥迪",
"name": "奥迪Q5 2017款 Plus 40 TFSI 豪华型"
}'根据 ID 查询
curl 'http://localhost:9200/specs/spec/1?pretty'执行结果:
{
"_index": "specs",
"_type": "spec",
"_id": "1",
"_version": 1,
"found": true,
"_source": {
"factory": "一汽-大众奥迪",
"name": "奥迪A6L 2018款 30周年年型 TFSI 进取型"
}
}GET API 是实时的,写入后可以立即按 ID 读取。搜索依赖索引 refresh,为了马上看到刚写入的三条数据,先手动刷新一次:
curl -X POST 'http://localhost:9200/specs/_refresh'搜索
查询 spec 下的全部文档:
curl 'http://localhost:9200/specs/spec/_search?pretty'结果的 hits.total 为 3,hits.hits 中是刚才写入的三条车型数据。
使用 match 查询
查询厂商字段中包含“奥迪”的文档:
curl -X POST 'http://localhost:9200/specs/spec/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"factory": "奥迪"
}
}
}'这次会匹配两条“一汽-大众奥迪”的文档。
再搜索“上汽大众”:
curl -X POST 'http://localhost:9200/specs/spec/_search?pretty' \
-H 'Content-Type: application/json' \
-d '{
"query": {
"match": {
"factory": "上汽大众"
}
}
}'搜索结果共有三条。第一条文档的 factory 正好是“上汽大众”,匹配程度最高;另外两条中的“大众”也会被 IK 分词器匹配到,所以同样出现在结果中,但 _score 较低。
Elasticsearch 默认按相关度分数排序,_score 越高,说明当前文档与查询条件的匹配程度越高。这里也能看出全文检索和数据库精确查询的区别:match 会先分析查询文本,再用分析得到的词项进行检索。
创建索引、写入文档和查询的更多参数,可以继续查看 Elasticsearch 5.6 的 Create Index API、Index API 和 Search API。