Elasticsearch 提供了 REST API,操作起来很方便。上一篇已经在 CentOS 7 上安装了 Elasticsearch 5.6.2 和 IK 中文分词器,这次继续用 curl 完成索引、文档和搜索的基本操作。

Elasticsearch 仍然只允许内网访问,不要把 9200 端口直接暴露到公网。本文只介绍单机操作,不涉及集群内容。

基本概念

刚接触 Elasticsearch 时,index、type、document 和 field 这些概念容易混淆。可以先和 MySQL 粗略对照:

ElasticsearchMySQL 中接近的概念
IndexDatabase 或 Table
TypeTable
DocumentRow
FieldColumn
MappingSchema

这个对照只方便理解,二者并不是一一对应。特别是同一索引下不同 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。

最后修改:2017 年 10 月 05 日
如果觉得我的文章对你有用,请随意赞赏