Elasticsearch总结

一、概述

        Elasticsearch(es)是建立在全文搜索引擎库 Apache Lucene™ 基础上的实时分布式搜索分析引擎。它通过隐藏 Lucene 的复杂性,提供一套简单的 RESTful API。它不仅有Lucene的能力,还是一个分布式的实时文档存储,每个字段可以被索引与搜索、还是一个分布式实时分析搜索引擎、能胜任上百个服务节点的扩展,并支持 PB 级别的结构化或者非结构化数据。es常被用作全文检索、结构化搜索、分析以及这三个功能的组合。

        es是面向文档的,对文档而不是像结构化数据那样的行列数据进行索引、检索、排序和过滤。它在存储整个对象或文档的同时会索引每个文档的内容,使之可以被检索。正因为es是在面向文档的,才使es能支持复杂的全文检索。es中很重要的一个数据结构是倒排索引(反向索引),它把要搜索的词作为key,把包含该词的文档作为value,由于包含该词的文档不止一个,所以这个value是文档的数组。

        一个es集群可以包含多个节点,每个节点可以包含多个索引。相应的每个索引可以包含多个类型(高版本逐渐取消多类型) 。 每个类型存储着多个文档 ,每个文档又有多个字段(es叫域),每个域都有自己的类型。需要注意的是相同索引不同类型下文档的域必须相同。

       es域的简单类型有:

关键字 说明
string 字符串,es5后被移除,被拆成keyword和text
keyword 精确匹配的字符串,不会做分词处理
text 全文检索的字符串,分析器会做分词处理
byte、short、integer、long 整型
float、double 浮点数
boolean 布尔型
date 日期

      es域的复杂类型有:

类型 说明 示例
多值域 域包含多个值,类似数组。用[ ]包围多个值,这些值的类型必须一样 { "sex": [ "male", "female" ]}
空域 存在null值的域即为空域,包括:null、[]、[null]  
多层级对象 多层JSON对象嵌套  
内部对象的映射 属性type为"object",属性properties中又是内部的对象映射  

        用法在官方手册已经有很多示例,请参考:

es官网:https://www.elastic.co/cn/

es中文官网:https://www.elastic.co/cn/

es中文文档:https://www.elastic.co/guide/cn/index.html

es参考手册:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

es Github源码:https://github.com/elastic/elasticsearch

二、集群和节点

       集群(cluster)由一个或多个拥有相同cluster.name配置的节点(实例)组成, 它们共同承担数据和负载的压力。当有新节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。节点有主节点和非主节点之分,主节点负责管理集群范围内所有的变更。

       分片(_shards)是数据的容器,被分配到集群内的各个节点里。分片其实就是Lucene实例,所以一个分片就是一个完整的搜索引擎。分片有主分片和副本分片之分,索引内任意一个文档都归属于一个主分片,所以主分片的数目决定着索引能够保存的最大数据量。实际上最大数据量还跟硬件、文档的大小和复杂程度、索引和查询文档的方式以及期望的响应时长等有关。主分片的数量在创建时被确定并且不能改变,因为每个文档存储在哪个主分片上是根据公式:shard = hash(routing) % number_of_primary_shards确定的,如果number_of_primary_shards发生了变化,原本保存的文档在主分片的位置就错误了。副本分片只是主分片的拷贝, 作为硬件故障时保护数据不丢失的冗余备份,并为搜索和返回文档等读操作提供服务。

       elasticsearch.yml配置说明如下:

配置项 说明
cluster.name 集群名称
node.name 节点名称
node.master 是否是主节点。es默认集群中的第一台机器为主节点,如果这台机挂了就会重新选主节点
node.data 该节点是否存储索引数据,默认为true
index.number_of_shards 索引的主分片个数,默认为5
index.number_of_replicas 索引的副本分片个数,默认为1
path.conf 配置文件的存储路径,默认是es根目录下的config文件夹
path.data 索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开
path.work 临时文件的存储路径,默认是es根目录下的work文件夹
path.logs 日志文件的存储路径,默认是es根目录下的logs文件夹
path.plugins 插件的存放路径,默认是es根目录下的plugins文件夹
bootstrap.mlockall 是否锁住内存,因为当jvm开始swapping时es的效率 会降低,所以要保证它不swap
network.bind_host 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0
network.publish_host 设置其它节点和该节点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址
network.host 同时设置bind_host和publish_host
transport.tcp.port 节点间交互的tcp端口,默认是9300
transport.tcp.compress 是否压缩tcp传输时的数据,默认为false
http.port 对外服务的http端口,默认为9200
http.max_content_length 内容的最大容量,默认100mb
http.enabled 是否使用http协议对外提供服务,默认为true
gateway.type gateway的类型,默认为local即为本地文件系统。可以设置为本地文件系统,分布式文件系统,hadoop的HDFS、amazon的s3服务器以及其它文件系统
gateway.recover_after_nodes 集群中N个节点启动后进行数据恢复,默认为1
gateway.recover_after_time 初始化数据恢复进程的超时时间,默认是5分钟
gateway.expected_nodes 集群中节点的数量,默认为2,一旦这N个节点启动,就会立即进行数据恢复
cluster.routing.allocation.node_initial_primaries_recoveries 初始化数据恢复时,并发恢复线程的个数,默认为4
cluster.routing.allocation.node_concurrent_recoveries 添加删除节点或负载均衡时并发恢复线程的个数,默认为4
indices.recovery.max_size_per_sec 数据恢复时限制的带宽,单位mb,默认为0,即无限制
indices.recovery.concurrent_streams 限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5
discovery.zen.minimum_master_nodes 有主节点资格的节点个数,默认为1
discovery.zen.ping.timeout 自动发现其它节点时ping连接超时时间,默认为3秒
discovery.zen.ping.multicast.enabled 是否打开多播发现节点,默认是true
discovery.zen.ping.unicast.hosts 设置主节点的初始列表,可以通过这些节点来自动发现新加入集群的节点
action.auto_create_index 是否自动创建索引
action.destructive_requires_name 是否禁止使用_all和通配符删除索引
script.groovy.sandbox.enabled 是否启用脚本

       修改配置有两种方式:

       1、持久性修改,使用关键字:persistent,集群重启后不失效;

       2、临时性修改,使用关键字:transient,集群重启后就会失效;

PUT http://$user:$passwd@$host:$port/_cluster/settings
{
    "persistent" : {
        配置名 : 值
    },
    "transient" : {
        配置名 : 值
    }
}

       常用API:

1:查看集群信息:

GET http://$user:$passwd@$host:$port/

2:查看集群的健康信息:

GET http://$user:$passwd@$host:$port/_cluster/health

三、分析器

文档的每个域都有两个重要属性:index和analyzer:

       1、index:控制怎样索引字符串,它可以是下面三个值:

              1>analyzed:只有string类型的index属性才可能有此值。默认会用分析器进行处理,以便进行全文检索;

              2>not_analyzed:不使用分析器处理,所以只能进行精确匹配;

              3>no:不索引这个域,所以这个域不会被搜索到;

       2、analyzer:指定在搜索和索引时使用的分析器。默认使用标准分析器(standard)分析器。

分析器对文档内容的分析包含以下过程:

       1、将文本分成适合倒排索引的独立的词条;

       2、将这些词条统一为标准格式以提高它们的“可搜索性”,比如:

              1>大小写转换;

              2>词根提取;

              3>同义词转换;

分析器实际上是将三个功能封装到了一个包里:

       1、字符过滤器

       字符串按顺序通过每个字符过滤器,过滤器的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将&转化成 `and`;

       2、分词器

       字符串被分词器分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条;

       3、token过滤器

       词条按顺序通过每个token过滤器。这个过程可能会改变词条(比如转换大小写),删除词条(比如像`a`,`and``the`等无用词),或者增加词条(比如增加同义词)。

       es常见的内置分析器有:

       1、标准分析器(standard):根据Unicode联盟定义的单词边界划分文本,删除绝大部分标点,最后将词条小写;

       2、简单分析器(simple):在任何不是字母的地方分隔文本,将词条小写;

       3、空格分析器(whitespace):在空格的地方划分文本;

       4、语言分析器:根据指定语言的特点,对文本进行划分;

       常用API:

1、查看文本放入字段后的拆词结果:

GET http://$user:$passwd@$host:$port/$index/_analyze
{
    "field": 字段名,
    "text": 文本内容
}

2、查看文本经过分析器处理后的结果:

GET http://$user:$passwd@$host:$port/$index/_analyze
{
    "analyzer": 分析器名,
    "text": 文本内容
}

3、创建自定义分析器:

PUT http://$user:$passwd@$host:$port/$index
{
    "settings": {
        "analysis": {
            "analyzer": {
                "dash_remove_analyzer": { //创建名为dash_remove_analyzer的分析器,用于去“-”
                    "tokenizer": "standard",
                    "stopwords": "_spanish_", //停用词使用预定义的西班牙语停用词列表
                    "char_filter": [
                        "dash_remove_char_filter"
                    ]
                }
            },
            "char_filter": {
                "dash_remove_char_filter": {
                    "type": "pattern_replace",
                    "pattern": "(\\S*)-(\\S*)|(\\S*)",
                    "replacement": "$1$2"
                }
            }
        }
    }
}

四、用户

五、索引

       常用API:

1:查看所有索引信息

GET http://$user:$passwd@$host:$port/$index/_cat/indices?v

2、查看某个索引信息:

GET http://$user:$passwd@$host:$port/$index

3、查看索引下类型下的映射信息:

GET http://$user:$passwd@$host:$port/$index/_mapping/$type

4:创建索引:

PUT http://$user:$passwd@$host:$port/$index
{
    "settings": {
        "number_of_shards": 1, //索引的主分片个数,默认值是5,这个配置在索引创建后不能修改
        "number_of_replicas" : 0 //每个主分片的副本分片个数,默认值是1,对于活动的索引库,这个配置可以随时修改
    },
    "mappings": {
        "$type": {
            "properties": {
                字段名1: {
                    "type": "text",
                    "analyzer": "english",
                    "fields": {
                        "keyword": {//定义分析器:字段名1.keyword
                            "type": "keyword",
                            "ignore_above": 512
                        },
                        "standard": {//定义分析器:字段名1.standard
                            "type": "text",
                            "analyzer": "standard"
                        }
                    }
                },
                字段名2: {
                    "type": "boolean"
                },
                字段名3: {
                    "type": "date",
                    "format": "yyyy-MM-dd HH:mm:ss"
                },
                字段名4: {
                    "type": "long"
                }
            }
        }
    }
}

5:修改索引配置:

PUT http://$user:$passwd@$host:$port/$index/_settings
{
    "refresh_interval": "2s"
}

6:新增域:

PUT http://$user:$passwd@$host:$port/$index/_mappings/$type
{
    "properties": {
        字段名: {
            "type": "string",
            "index": "not_analyzed"
        }
    }
}

7:删除索引,可以有多种方式:

DELETE /$index
DELETE /$index0,$index1
DELETE /$index*
DELETE /_all
DELETE /*

六、文档维护

       文档类似于传统关系数据库中表的一条记录,es用关键字_doc表示。每个文档必须包含三个元素:文档在哪存放(_index)、文档表示的对象类别(_type)、文档唯一标识(_id)。

       1、新增或修改:

PUT /$index/$type/$id
{
    "name": "tom",
    "age": 32,
    "about": "I love to go rock climbing",
    "interests": [ "music" , "sport"]
}
PUT /$index/$type/$id?version=5&version_type=external //创建或修改成功后的版本号是5的文档
{
    "name": "tom",
    "age": 32,
    "about": "I love to go rock climbing",
    "interests": [ "music" , "sport"]
}

新增 

POST /$index/$type/
{
    "name": "tom",
    "age": 32,
    "about": "I love to go rock climbing",
    "interests": [ "music" , "sport"]
}

 新增,如果存在则返回409 Conflict,如果创建成功返回201 Created。

PUT /$index/$type/$id?op_type=create
{
    "name": "tom",
    "age": 32,
    "about": "I love to go rock climbing",
    "interests": [ "music" , "sport"]
}
PUT /$index/$type/$id/_create
{
    "name": "tom",
    "age": 32,
    "about": "I love to go rock climbing",
    "interests": [ "music" , "sport"]
}

修改

POST /$index/$type/$id/_update
{
    "doc":{
        "height":185
    }
}

使用脚本修改

POST /$index/$type/$id/_update
{
    "script" : "ctx._source.height+=1"
}

或者: 

POST /$index/$type/$id/_update
{
    "script" : "ctx._source.interests+=new_interests",
    "params" : {
      "new_interests" : "film"
   }
}

或者指定ctx.op=delete进行删除:

POST /$index/$type/$id/_update
{
    "script" : "ctx.op = ctx._source.height > height ? 'delete' : 'none'",
    "params" : {
        "height": 185
    }
}

指定id的文档如果不存在时需要es自动新增,如果由于版本冲突更新失败时可以用retry_on_conflict指定重试的次数,比如:

POST /$index/$type/$id/_update?retry_on_conflict=5
{
    "script" : "ctx._source.height+=1",
    "upsert": {
        "height": 0
   }
}

删除,成功返回200 ok,失败返回404 Not Found

DELETE /$index/$type/$id

_delete_by_query

 

批量操作:

POST /$index/$type/_bulk
{"index":{"_index":"website","_type":"blog"}}\n
{"title":"Mysecondblogpost"}\n
{"create":{"_index":"website","_type":"blog","_id":"123"}}\n
{"title":"Myfirstblogpost"}\n
{"update":{"_index":"website","_type":"blog","_id":"123","_retry_on_conflict":3}}\n
{"doc":{"title":"Myupdatedblogpost"}}\n
{"delete":{"_index":"website","_type":"blog","_id":"123"}}\n

       2、查询:

支持多索引,多类型搜索:

GET /_search?size=5&from=0 //分页查询指定节点下所有索引的文档,每页显示5条,显示第1页
GET /$index1/_search //查询指定节点下索引index1的文档

 

GET /$index1,$index2/_search //查询指定节点下索引index1、index2的文档

 

GET /a*,b*/_search //查询指定节点下以a,b开头的索引的文档

 

GET /$index1/$type1/_search //查询指定节点下索引是index1,类型是type1的文档

 

GET /$index1,$index2/$type1,$type2/_search //查询指定节点下索引是index1和index2,类型是type1和type2的文档

 

GET /_all/$type1,$type2/_search //查询指定节点下所有索引中类型是type1和type2的文档

 

 

GET /$index/$type/$id?pretty //pretty方式展示文档信息
GET /$index/$type/$id?_source=title,text //只展示title和text字段

 

GET /$index/$type/$id?_source //只返回_source中的字段

如果存在指定id的文档,则返回200 ok的状态码,否则返回404 Not Found的状态码。 

GET /index/type/_search //查询所有文档
GET /_search?timeout=10ms //10ms必须返回,所以返回的文档可能为空

轻量搜索,查name包含tom的文档,条件与条件之间空格分隔,+前缀表示必须与查询条件匹配,-前缀表示一定不与查询条件匹配,没有+或者-的所有其他条件都是可选的(匹配的越多,文档就越相关)。 

GET /index/type/_search?q=+title:完善 -content:认证

轻量搜索,查不管哪个字段,包含tom的文档。

GET /index/type/_search?q=认证
GET /index/type/_search?q=+name:(mary john) +date:>2014-09-10 +(aggregations geo)

请求体查询,在es中是支持GET请求的请求体的。但因为带请求体的GET请求并不被广泛支持,所以同时支持POST请求的请求体。

空查询:

GET /_search
{}

分页 

GET /_search
{
  "from": 30,
  "size": 10
}

查询表达式:

match_all:常用于空查询或与filter结合使用:

GET /_search
{
    "query": {
        "match_all": {}
    }
}

match:根据字段是否是text类型,决定是否用分词器进行分词:

GET /_search
{
    "query" : {
        "match" : {
            "name" : "tom" 
        }
    }
}

 multi_match:可以在多个字段上执行相同的match查询:

{
    "multi_match": {
        "query": "full text search",
        "fields": [ "title", "body" ]
    }
}

 match_phrase:查询短语的match查询:

{
    "match_phrase": {
        "content": {
            "query": "my name is Tom",
            "slop":  1
        }
    }
}

 range:找出那些落在指定区间内的数字或者时间,可以使用:gt(大于)、gte(大于等于)、lt(小于)、lte(小于等于):

{
    "range": {
        "age": {
            "gte": 20,
            "lt": 30
        }
    }
}

term: 用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些not_analyzed的字符串,区分大小写:

{"term": {"age": 26}}
{"term": {"date": "2014-09-01"}}
{"term": {"public": true}}
{"term": {"tag":  "full_text"}}

terms:用于精确值匹配,但它允许你指定多值进行匹配,区分大小写。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:

{"terms": {"tag": ["search","full_text","nosql"]}}
 

exists、missing:用于查询指定字段中是否有值,相当于sql中的IS NOT NULL和IS NULL:

{
    "exists": {
        "field": "title"
    }
}
GET /index/type/_search
{
    "query" : {
        "match" : { //查询表达式,查name是tom的文档
            "name" : "tom" 
        }
    },
    "highlight": { //高亮显示
        "fields" : {
            "about" : {}
        }
    }
}

复合查询 

GET /index/type/_search 
{
    "query" : {
        "bool": {
            "must": {
                "match" : { //查name是tom
                    "name" : "tom" 
                }
            },
            "filter": { //过滤器,并且年龄大于30 
                "range" : {
                    "age" : { "gt" : 30 } 
                }
            }
        }
    }
}
GET /index/type/_search 
{
    "query" : {
        "match" : { //全文检索:即查询包含rock、climbing或两个词都包含(即使顺序颠倒)的文档
            "about" : "rock climbing"
        }
    }
}
GET /index/type/_search 
{
    "query" : {
        "match_phrase" : { //短语搜索,即查询包含整个短语的文档,只包含单个词的不会查到
            "about" : "rock climbing"
        }
    }
}
GET /index/type/_search
{
  "aggs": { //聚合,查字段interests中每个元素出现的次数
    "all_interests": {
      "terms": { "field": "interests" }
    }
  }
}
GET /index/type/_search
{
    "aggs" : {
        "all_interests" : {
            "terms" : { "field" : "interests" },
            "aggs" : { //分级聚合,查询每个interests元素中,age的平均值
                "avg_age" : {
                    "avg" : { "field" : "age" }
                }
            }
        }
    }
}

同时获取多个文档,必须通过docs数组指定_index,_type以及_id,还可以使用_source指定文档内容返回的字段。

GET /_mget
{
   "docs" : [
      {
         "_index" : "website",
         "_type" :  "blog",
         "_id" :    2
      },
      {
         "_index" : "website",
         "_type" :  "pageviews",
         "_id" :    1,
         "_source": "views"
      }
   ]
}

如果是相同的_index或_type,可以统一放在URL的path中

GET /$index/$type/_mget
{
   "docs" : [
      {
         "_id" :    1
      },
      {
         "_id" :    2,
         "_source": "views"
      }
   ]
}

如果只有ID不同,可以使用ids代替docs:

GET /$index/$type/_mget
{
   "ids" : [ "1", "2" ]
}

 

你可能感兴趣的:(elasticsearch,es,Lucene,全文检索,分布式,检索)