数据检索

CRUD

创建与更新

在 ElasticSearch 中,Index 这一动作类比于 CRUD 中的 Create 与 Update,当我们尝试为某个不存在的文档建立索引时,会自动根据其类似与 ID 创建新的文档,否则就会对原有的文档进行修改。ElasticSearch 使用 PUT 请求来进行 Index 操作,你需要提供索引名称、类型名称以及可选的 ID,格式规范为 :http://localhost:9200/<index>/<type>/[<id>]。其中索引名称可以是任意字符,如果 ElasticSearch 中并不存在该索引则会自动创建。类型名的原则很类似于索引,不过其与索引相比会指明更多的细节信息:

  • 每个类型有自己独立的 ID 空间
  • 不同的类型有不同的映射 (Mappings),即不同的属性 / 域的建立索引的方案
  • 尽可能地在一起搜索请求中只对某个类型或者特定的类型进行搜索

典型的某个 Index 请求为

curl -XPUT "http://localhost:9200/movies/movie/1" -d'
{
    "title": "The Godfather",
    "director": "Francis Ford Coppola",
    "year": 1972
}'

ElasticSearch 仅会允许版本号高于原文档版本号的修改发生。注意,如果你并没有提供文档编号,那么应该使用 POST 方法来创建新的索引

POST /website/blog/
{
  "title": "My second blog entry",
  "text":  "Still trying this out...",
  "date":  "2014/01/01"
}

Search | 搜索

ElasticSearch 为我们提供了通用的_bulk端点来在单请求中完成多文档创建操作,不过这里为了简单起见还是分为了多个请求进行执行。ElasticSearch 中搜索主要是基于_search这个端点进行的,其标准请求格式为 :<index>/<type>/_search,其中 index 与 type 都是可选的。换言之,我们可以以如下几种方式发起请求

  • http://localhost:9200/_search - 搜索所有的 Index 与 Type
  • http://localhost:9200/movies/_search - 搜索 Movies 索引下的所有类型
  • http://localhost:9200/movies/movie/_search - 仅搜索包含在 Movies 索引 Movie 类型下的文档

全文搜索

ElasticSearch 的 Query DSL 为我们提供了许多不同类型的强大的查询的语法,其核心的查询字符串包含很多查询的选项,并且由 ElasticSearch 编译转化为多个简单的查询请求。最简单的查询请求即是全文检索,譬如我们这里需要搜索关键字 :kill:

创建数据

curl -XPOST "http://localhost:9200/_search" -d'
{
    "query": {
        "query_string": {
            "query": "kill"
        }
    }
}'

指定域搜索

在上文简单的全文检索中,我们会搜索每个文档中的所有域。而很多时候我们仅需要对指定的部分域中文档进行搜索操作,譬如我们要搜索仅在标题中出现ford字段的文档

curl -XPOST "http://localhost:9200/_search" -d'
{
    "query": {
        "query_string": {
            "query": "ford",
            "fields": ["title"]
        }
    }
}'

Geo

PUT /my_locations
{
    "mappings": {
        "location": {
            "properties": {
                "pin": {
                    "properties": {
                        "location": {
                            "type": "geo_point"
                        }
                    }
                }
            }
        }
    }
}

PUT /my_locations/location/1
{
    "pin" : {
        "location" : {
            "lat" : 40.12,
            "lon" : -71.34
        }
    }
}
GET /my_locations/location/_search
{
    "query": {
        "bool" : {
            "must" : {
                "match_all" : {}
            },
            "filter" : {
                "geo_distance" : {
                    "distance" : "200km",
                    "pin.location" : {
                        "lat" : 40,
                        "lon" : -70
                    }
                }
            }
        }
    }
}

ElasticSearch 是一个基于 Lucene 的搜索服务器;它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful web 接口。根据其官方定义,我们可以将 ElasticSearch 中的术语组件与 MySQL 进行横向对比:

MySQL => Databases => Tables => Columns/Rows
Elasticsearch => Indices => Types => Documents with Properties

基本的术语名词解释如下:

  • 索引 / Index: 类似于 MySQL 中的数据库;
  • 类型 / Type: 类似于 MySQL 中的表,我们可以为 Type 定义相对应的 映射 / Mappings ( 类似于 MySQL 中的 Schema ) 以优化索引性能;

  • 文档 / Document: 类似于 MySQl 中的记录,是信息聚合的最小单元。

与集群相关的名词还包括:

  • 集群 / Cluster: ElastichSearch 可以作为一个独立的搜索服务器工作,也可以在多台协同工作的服务器上运行,统称为一个集群,其中有一台被作为 Master,其他为 Slave;
  • 节点 / Node: 一般来说一个机器部署一个 Node。

  • 分片 / Shard: 指的是一个 Index 分成多少份,这些 Shards 会分散到各个 Node 上面,类似于 HDFS 的文件块。

  • 副本 / Replica: 副本是针对每个分片的,可以为一个分片设置多个副本,分布在不同的节点上,即是容错,也可以提高查询任务的性能,原理同 HDFS 的文件块副本机制。

鉴于 Logstash 更多的关注于日志聚合,因此将 ElasticSearch 与 Kibana 剥离部署。如果有对于 Linux 命令不太熟悉的,可以参考 Linux DevOps 中常用命令与技巧清单

单机配置

ElasticSearch 与 Kibana 的安装还是较为方便的,直接下载 jar 包运行即可,具体过程可以查看官方指南;不过自 5.x 版本之后,ElasticSearch 会在启动时进行系统检测,可能报的异常与解决方案如下所示:

# ElasticSearch 不允许以 root 用户运行,需要创建并且切换用户
useradd elastic
su elastic

# 以 root 用户设置文件最大描述符
# max file descriptors [8192] for elasticsearch process is too low, increase to at least [65536]
$ sudo ulimit -n 65536

# 修改 MMap
$ sudo sysctl -w vm.max_map_count=262144

# max size virtual memory [10018979840] for user [elastic] is too low, increase to [unlimited]
$ vim /etc/security/limits.conf
* hard memlock unlimited
* soft memlock unlimited
* hard nofile 65536
* soft nofile 65536
*  - as unlimited

CRUD

Query: 搜索

# 简单查询
GET _search
{
  "query": {
    "match": {
      "${FIELD}": "${TEXT}"
    }
  }
}

# 复杂查询
GET _search
{
  "query": {
    "match": {
      "${FIELD}": {
        "query": "${TEXT}",
        "${OPTION}": "${VALUE}"
      }
    }
  }
}

# 多重匹配
"multi_match": {
  "query": "Elastic",
  "fields": ["user.*", "title^3"],
  "type": "best_fields"
}

# 布尔值计算
"bool": {
  "must": [],
  "must_not": [],
  "filter": [],
  "should": [],
  "minimum_should_match" : 1
}

# 范围查询
"range": {
  "age": {
    "gte": 10,
    "lte": 20,
    "boost": 2
  }
}

针对于复杂查询,ElasticSearch 还提供了 QueryString 查询格式:

# 默认查询全部属性
GET /_search?q=pony

# 操作符
GET /_search?q=title:(joli OR code) AND author:"Damien Alexandre"^2

# 通配符或者特殊字符
GET /_search?q=_exists_:title OR title:singl? noneOrAnyChar*cter

# 模糊搜索与范围搜索
GET /_search?q=title:elastichurch~3 AND date:[2016-01-01 TO 2018-12-31]

# Query DSL
下一页