数据检索

CRUD

创建与更新

ElasticSearch中,Index这一动作类比于CRUD中的CreateUpdate,当我们尝试为某个不存在的文档建立索引时,会自动根据其类似与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,其中indextype都是可选的。换言之,我们可以以如下几种方式发起请求

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

全文搜索

ElasticSearchQuery 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更多的关注于日志聚合,因此将ElasticSearchKibana剥离部署。如果有对于Linux命令不太熟悉的,可以参考 Linux DevOps中常用命令与技巧清单

单机配置

ElasticSearchKibana的安装还是较为方便的,直接下载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
下一页