ES

 MVC 配置(非Boot)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd">
    <!-- 配置es包扫描 -->
    <elasticsearch:repositories base-package="com.huangliwei.elasticsearch.dao" />

    <!-- 配置service包扫描 -->
    <context:component-scan base-package="com.huangliwei.elasticsearch.service" />

    <!-- 配置elasticsearch连接 -->
    <elasticsearch:transport-client id="client"
        cluster-nodes="127.0.0.1:9300" />

    <!-- springdata整合elasticsearch提供template -->
    <bean id="elasticsearchTemplate"
        class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client"></constructor-arg>
    </bean>
</beans>

2018年Q2, Elasticsearch 更新到6.2版本, 6.3版本还未正式发布,如果准备在生产环境使用,比较推荐使用较老的5.6.x版本或2.x版本,一方面比较稳定、另外资料也比较多

如果使用Java技术栈,你很可能会使用Spring Boot全家桶,当前Spring Boot更新到2.x版本, 默认spring-boot-starter-data-elasticsearch 默认的ES版本为5.6.9;如果你仍然使用Spring Boot 1.x版本,那么默认的Elastisearch版本为2.x

客户端

Java技术栈目前有三种可以选择 Node Client, Transport Client, Rest API, 需要注明的是,官方已经标明NodeClient 已经过期,Transport Client 将在7.x版本开始不再支持, 最终会在7.x 统一到Rest API。目前Transport Client使用范围比较广;Rest API方式兼容性较好;除非在In-memory模式下运行单元测试,否则不推荐NodeClient

 

1.2ElasticSearch的基本概念
Index
  类似于mysql数据库中的database


Type
  类似于mysql数据库中的table表,es中可以在Index中建立type(table),通过mapping进行映射。


Document
  由于es存储的数据是文档型的,一条数据对应一篇文档即相当于mysql数据库中的一行数据row,一个文档中可以有多个字段也就是mysql数据库一行可以有多列。


Field
  es中一个文档中对应的多个列与mysql数据库中每一列对应


Mapping
  可以理解为mysql或者solr中对应的schema,只不过有些时候es中的mapping增加了动态识别功能,感觉很强大的样子,其实实际生产环境上不建议使用,最好还是开始制定好了对应的schema为主。


indexed
  就是名义上的建立索引。mysql中一般会对经常使用的列增加相应的索引用于提高查询速度,而在es中默认都是会加上索引的,除非你特殊制定不建立索引只是进行存储用于展示,这个需要看你具体的需求和业务进行设定了。


Query DSL
  类似于mysql的sql语句,只不过在es中是使用的json格式的查询语句,专业术语就叫:QueryDSL

GET/PUT/POST/DELETE

分别类似与mysql中的select/update/delete…

ElasticSearch Head (安装插件)

使用ElasticSearch API 实现CRUD(ES基本命令操作)

#添加索引
#带自定义配置的添加:
PUT /lib/
{
  "settings":{
      "index":{
        "number_of_shards": 5,   # 默认5个,不能修改
        "number_of_replicas": 1   # 随时修改,默认1个
        }
      }
}
# 使用默认配置的添加: lib前后加 / 和不加没区别,后面加了/ 反而在kibana中没提示
PUT lib


# 查看索引命令
GET /lib/_settings   # 查询单个
GET _all/_settings   # 查询所有

 

# 添加文档:
# 指定id为1,如果不指定,需要用post提交,elasticsearch自动生成
PUT /lib/user/1 
{
    "first_name" :  "Jane",
    "last_name" :   "Smith",
    "age" :         32,
    "about" :       "I like to collect rock albums",
    "interests":  [ "music" ]
}


 # 这里没有id,自动生成,使用POST
POST /lib/user/   
{
    "first_name" :  "Douglas",
    "last_name" :   "Fir",
    "age" :         23,
    "about":        "I like to build cabinets",
    "interests":  [ "forestry" ]
}


# _source元数据分析其实就是我们在添加文档时request body中的内容指定返回的结果中含有哪些字段:
GET /lib/user/1
GET /lib/user/
GET /lib/user/1?_source=age,interests   # _source:指定查询id为1的age和interests两个字段

 

# 覆盖更新,相当于重新插入,这里没覆盖到的字段,更新后就没了,可能会引起丢失字段
PUT /lib/user/1    
{
    "first_name" :  "Jane",
    "last_name" :   "Smith",
    "age" :         36,
    "about" :       "I like to collect rock albums",
    "interests":  [ "music" ]
}

# 正确更新
POST /lib/user/1/_update  
{
  "doc":{
      "age":33
      }
}


# 删除一个文档
DELETE /lib/user/1

# 删除一个索引
DELETE /lib


 

使用es提供的Multi Get API:

使用Multi Get API可以通过索引名、类型名、文档id一次得到一个文档集合,文档可以来自同一个索引库,也可以来自不同索引库

#  可以指定具体的字段  也可以不指定
GET /_mget
{
    "docs":[
       {
           "_index": "lib",
           "_type": "user",
           "_id": 1,
           "_source": "interests"   # 可以指定具体的字段
       },
       {
           "_index": "lib",
           "_type": "user",
           "_id": 2,
           "_source": ["age","interests"]  # 可以指定具体的字段
       }
     ]
}

# 获取同索引同类型下的不同文档:

GET /lib/user/_mget
{
    "docs":[
       {
           "_id": 1
       },
       {
           "_type": "user",
           "_id": 2
       }
     ]
}
GET /lib/user/_mget
{
   "ids": ["1","2"]
}

 

使用Bulk API 实现批量操作

bulk的格式:(_mget只能获取,bulk能增删改查)

 # create:文档不存在时创建
 # update:更新文档
 # index:创建新文档或替换已有文档
 # delete:删除一个文档


POST lib/user/_bulk
{"delete":{"_index":"lib","_type":"user","_id":"1"}}


# 批量添加

POST /lib2/books/_bulk
{"index":{"_id":1}}       # 插入_id为1,内容为java、55的
{"title":"Java","price":55}
{"index":{"_id":2}}       # 插入_id为2...
{"title":"Html5","price":45}
{"index":{"_id":3}}
{"title":"Php","price":35}
{"index":{"_id":4}}
{"title":"Python","price":50}


# 批量获取

GET /lib2/books/_mget
{
"ids": ["1","2","3","4"]
}



# 删除:没有请求体

POST /lib2/books/_bulk
{"delete":{"_index":"lib2","_type":"books","_id":4}}
{"create":{"_index":"tt","_type":"ttt","_id":"100"}}
{"name":"lisi"}
{"index":{"_index":"tt","_type":"ttt"}}
{"name":"zhaosi"}
{"update":{"_index":"lib2","_type":"books","_id":"4"}}
{"doc":{"price":58}}


bulk一次最大处理多少数据量:

bulk会把将要处理的数据载入内存中,所以数据量是有限制的,最佳的数据量不是一个确定的数值,
    它取决于你的硬件,你的文档大小以及复杂性,你的索引以及搜索的负载。
  一般建议是1000-5000个文档,大小建议是5-15MB,默认不能超过100M,
    可以在es的配置文件(即$ES_HOME下的config下的elasticsearch.yml)中。


 支持的数据类型:

(1)核心数据类型(Core datatypes)

字符型:string,string 类型包括text 和 keyword

最主要区别:text会被分词,keyword不会被分词
text类型被用来索引长文本,在建立索引前会将这些文本进行分词,转化为词的组合,建立索引。
允许es来检索这些词语。text类型不能用来排序和聚合。Keyword类型不需要进行分词,
可以被用来检索过滤、排序和聚合。keyword 类型字段只能用本身来进行检索


数字型:long, integer, short, byte, double, float
日期型:date
布尔型:boolean
二进制型:binary

 (2)复杂数据类型(Complex datatypes)

数组类型(Array datatype):数组类型不需要专门指定数组元素的type,例如:
字符型数组: [ “one”, “two” ]
整型数组:[ 1, 2 ]
数组型数组:[ 1, [ 2, 3 ]] 等价于[ 1, 2, 3 ]
对象数组:[ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }]
对象类型(Object datatype):_ object _ 用于单个JSON对象;
嵌套类型(Nested datatype):_ nested _ 用于JSON数组;

 (3)地理位置类型(Geo datatypes)

地理坐标类型(Geo-point datatype):_ geo_point _ 用于经纬度坐标;
地理形状类型(Geo-Shape datatype):_ geo_shape _ 用于类似于多边形的复杂形状;

(4)特定类型(Specialised datatypes)

IPv4 类型(IPv4 datatype):_ ip _ 用于IPv4 地址;
Completion 类型(Completion datatype):_ completion 提供自动补全建议;
Token count 类型(Token count datatype): token_count _ 用于统计做了标记的字段的index数目,该值会一直增加,不会因为过滤条件而减少。
mapper-murmur3
类型:通过插件,可以通过 _ murmur3 _ 来计算 index 的 hash 值;
附加类型(Attachment datatype):采用 mapper-attachments
插件,可支持_ attachments _ 索引,例如 Microsoft Office 格式,Open Document 格式,ePub, HTML 等。

支持的属性:

"store":false  //是否单独设置此字段的是否存储而从_source字段中分离,默认是false,只能搜索,不能获取值

"index": true  // 分词,不分词是:false,设置成false,字段将不会被索引,默认每个都会创建索引

"analyzer":"ik"  // 指定分词器,默认分词器为standard analyzer

"boost":1.23  // 字段级别的分数加权,默认值是1.0

"doc_values":false  // 对not_analyzed字段,默认都是开启,分词字段不能使用,对排序和聚合能提升较大性能,节约内存

"fielddata":{"format":"disabled"}  // 针对分词字段,参与排序或聚合时能提高性能,不分词字段统一建议使用doc_value

"fields":{"raw":{"type":"string","index":"not_analyzed"}} //可以对一个字段提供多种索引模式,同一个字段的值,一个分词,一个不分词
       
"ignore_above":100 //超过100个字符的文本,将会被忽略,不被索引

"include_in_all":ture //设置是否此字段包含在_all字段中,默认是true,除非index设置成no选项

"index_options":"docs"//4个可选参数docs(索引文档号) ,freqs(文档号+词频),positions(文档号+词频+位置,通常用来距离查询),offsets(文档号+词频+位置+偏移量,通常被使用在高亮字段)分词字段默认是position,其他的默认是docs

"norms":{"enable":true,"loading":"lazy"}//分词字段默认配置,不分词字段:默认{"enable":false},存储长度因子和索引时boost,建议对需要参与评分字段使用 ,会额外增加内存消耗量

"null_value":"NULL"//设置一些缺失字段的初始化值,只有string可以使用,分词字段的null值也会被分词

"position_increament_gap":0//影响距离查询或近似查询,可以设置在多值字段的数据上火分词字段上,查询时可指定slop间隔,默认值是100

"search_analyzer":"ik"//设置搜索时的分词器,默认跟ananlyzer是一致的,比如index时用standard+ngram,搜索时用standard用来完成自动提示功能

"similarity":"BM25"//默认是TF/IDF算法,指定一个字段评分策略,仅仅对字符串型和分词类型有效

"term_vector":"no"//默认不存储向量信息,支持参数yes(term存储),with_positions(term+位置),with_offsets(term+偏移量),with_positions_offsets(term+位置+偏移量) 对快速高亮fast vector highlighter能提升性能,但开启又会加大索引体积,不适合大数据量用

 映射的分类:


# dynamic设置可以适用在根对象上或者object类型的任意字段上,给索引lib2创建映射类型

# dynamic 的值为下列3个:

# true:默认值。动态添加字段
# false:忽略新字段
# strict:如果碰到陌生字段,抛出异常

POST /lib2
{
    "settings":{
    "number_of_shards" : 3,
    "number_of_replicas" : 0
    },
     "mappings":{
      "books":{
        "properties":{
            "title":{"type":"text"},
            "name":{"type":"text","index":false},
            "publish_date":{"type":"date","index":false},
            "price":{"type":"double"},
            "number":{"type":"integer"}
        }
      }
     }
}




POST /lib2
{
    "settings":{
    "number_of_shards" : 3,
    "number_of_replicas" : 0
    },
     "mappings":{
      "books":{
        "properties":{
            "title":{"type":"text"},
            "name":{"type":"text","index":false},
            "publish_date":{"type":"date","index":false},
            "price":{"type":"double"},
            "number":{
                "type":"object",
                "dynamic":true
            }
        }
      }
     }
}

 

 2.7基本查询(Query查询)

PUT /lib3
{
    "settings":{
    "number_of_shards" : 3,
    "number_of_replicas" : 0
    },
     "mappings":{
      "user":{
        "properties":{
            "name": {"type":"text"},
            "address": {"type":"text"},
            "age": {"type":"integer"},
            "interests": {"type":"text"},
            "birthday": {"type":"date"}
        }
      }
     }
}

PUT lib3/user/1
{
  "name":"zhang san",
  "address": "shatian",
  "age":18,
  "interests": "drink,dance",
  "birthday": "2018-05-21"
}
PUT lib3/user/2
{
  "name":"li si",
  "address": "tongfan",
  "age":28,
  "interests": "shopping",
  "birthday": "2000-01-21"
}
PUT lib3/user/3
{
  "name":"wang wu",
  "address": "guangfeng",
  "age":20,
  "interests": "reading,drink,dance",
  "birthday": "2015-05-21"
}

GET /lib3/user/_search?q=name:lisi
GET /lib3/user/_search?q=name:zhaoliu&sort=age:desc   # 排序字段是long或者integer等数值

term查询和terms查询(不分词)


# term query会去倒排索引中寻找确切的term,它并不知道分词器的存在。这种查询适合
# keyword 、numeric、date没有分词的。【直接查name没有结果,因为name是text,term中输入的词不会被分词,match会被分词】

term:查询某个字段里含有某个关键词的文档


# 精确查找,term中的field不能有空格等,因为倒排索引后都是一堆的词,而不是短语,(短语使用# match_phrase),
# 所以如果字段内容是:a,b,c ,使用term去查b,c 肯定是查不到的。因为term中field不会被分词,那么就是# 说需要匹配b,c整体,
# 但是a,b,c被拆分了a b c 所以匹配不到。


# term:查找interests 字段为 changge
GET /lib3/user/_search/
{
  "query": {
      "term": {"interests": "changge"}
  }
}


# terms:查询某个字段里含有多个关键词的文档

GET /lib3/user/_search
{
    "query":{
        "terms":{
            "interests": ["hejiu","changge"]
       }
   }
}


# 控制查询返回的数量
GET /lib3/user/_search
{
    "from":0,    # 从哪个开始
    "size":2,    # 取几个
    "query":{
        "terms":{
            "interests": ["hejiu","changge"]
        }
    }
}


# 返回版本号
GET /lib3/user/_search
{
    "version":true,   # 默认没有版本号
    "query":{
        "terms":{
            "interests": ["hejiu","changge"]
        }
    }
}


match查询(分词)

# match query知道分词器的存在,会对filed进行分词操作,然后再查询
GET /lib3/user/_search
{
    "query":{
        "match":{
            "name": "zhaoliu"
        }
    }
}

GET /lib3/user/_search
{
    "query":{
        "match":{
            "age": 20
        }
    }
}

# match_all:查询所有文档
GET /lib3/user/_search
{
  "query": {
    "match_all": {}
  }
}


# multi_match:可以指定多个字段
GET /lib3/user/_search
{
    "query":{
        "multi_match": {
            "query": "lvyou",
            "fields": ["interests","name"]
         }
    }
}


# match_phrase:短语匹配查询

# ElasticSearch引擎首先分析(analyze)查询字符串,从分析后的文本中构建短语查询,这意味着必须匹配 
# 短语中的所有分词,并且保证各个分词的相对位置不变:
GET lib3/user/_search
{
  "query":{  
      "match_phrase":{  
         "interests": "duanlian,shuoxiangsheng"
      }
   }
}


# 指定返回的字段
GET /lib3/user/_search
{
    "_source": ["address","name"],
    "query": {
        "match": {
            "interests": "changge"
        }
    }
}


# 控制加载的字段
GET /lib3/user/_search
{
    "query": {
        "match_all": {}
    },
    
    "_source": {
          "includes": ["name","address"],  # 包含的字段
          "excludes": ["age","birthday"]   # 排除的字段
      }
}


# 使用通配符 *
GET /lib3/user/_search
{
    "_source": {
          "includes": "addr*",
          "excludes": ["name","bir*"]
        
    },
    "query": {
        "match_all": {}
    }
}

# 使用sort实现排序
# desc:降序,asc升序:
GET /lib3/user/_search
{
    "query": {
        "match_all": {}
    },
    "sort": [
        {
           "age": {
               "order":"asc"
           }
        }
    ]
}

GET /lib3/user/_search
{
    "query": {
        "match_all": {}
    },
    "sort": [
        {
           "age": {
               "order":"desc"
           }
        }
    ]
}



# 前缀匹配查询
GET /lib3/user/_search
{
  "query": {
    "match_phrase_prefix": {
        "name": {
            "query": "zhao"   # 匹配一个词的前缀
        }
    }
  }
}


# range:实现范围查询

# from,to:这2个默认包含边界
# gte:大于等于,gt大于;
# lte :小于等于,lt小于;
# include_lower:是否包含范围的左边界,默认是true
# include_upper:是否包含范围的右边界,默认是true
GET /lib3/user/_search
{
    "query": {
        "range": {
            "birthday": {
                "from": "1990-10-10",
                "to": "2018-05-01"
            }
        }
    }
}

GET /lib3/user/_search
{
    "query": {
        "range": {
            "age": {
                "from": 20,
                "to": 25,
                "include_lower": true,
                "include_upper": false
            }
        }
    }
}



# wildcard查询(wildcard中文:通配符)
# 允许使用通配符* 和 ?来进行查询*代表0个或多个字符?代表任意一个字符
GET /lib3/user/_search
{
    "query": {
        "wildcard": {
             "name": "zhao*"
        }
    }
}
GET /lib3/user/_search
{
    "query": {
        "wildcard": {
             "name": "li?i"
        }
    }
}


# fuzzy实现模糊查询,性能低value:查询的关键字boost:查询的权值,默认值是1.0
# fuzziness :参考,默认0.5,填写“auto”,或者>5表示能编辑2次,老实说,没太明白……,估计也不常用吧
# prefix_length:指明区分词项的共同前缀长度,默认是0,前缀必须匹配串的长度
# max_expansions:查询中的词项可以扩展的数目,默认可以无限大
GET /lib3/user/_search
{
    "query": {
        "fuzzy": {
             "interests": "chagge"
        }
    }
}

GET /lib3/user/_search
{
    "query": {
        "fuzzy": {
             "interests": {
                 "value": "chagge"
             }
        }
    }
}




# 高亮搜索结果
GET /lib3/user/_search
{
    "query":{
        "match":{
            "interests": "changge"
        }
    },
    "highlight": {
        "fields": {
             "interests": {}
        }
    }
}




# boost提升权重创建mapping时,将title的权重设置为普通的2倍,那么最终匹配的得分会受影响,以达到获# 取用户想要的排名结果。

#设置mapping时设定。
PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "title": {
          "type": "text",
          "boost": 2     # 将title的值匹配的权重设置为普通的2倍
        },
        "content": {
          "type": "text"
        }
      }
    }
  }
}


#查询时设定:
GET lib3/user/_search
{
  "query": {
    "match": {
      "name": {
        "query": "zhan si san",
        "boost":"2"    # 查询提升匹配的分值_score
      }
    }
  }
}



# Filter查询filter是不计算相关性的,同时可以cache。因此,filter速度要快于query。
# 插入数据等待查询
POST /lib4/items/_bulk
{"index": {"_id": 1}}
{"price": 40,"itemID": "ID100123"}
{"index": {"_id": 2}}
{"price": 50,"itemID": "ID100124"}
{"index": {"_id": 3}}
{"price": 25,"itemID": "ID100124"}
{"index": {"_id": 4}}
{"price": 30,"itemID": "ID100125"}
{"index": {"_id": 5}}
{"price": null,"itemID": "ID100127"}

# 简单的过滤查询
GET /lib4/items/_search
{ 
       "post_filter": {
             "term": {
                 "price": 40
             }
       }
}

GET /lib4/items/_search
{
      "post_filter": {
          "terms": {
                 "price": [25,40]
              }
        }
}

GET /lib4/items/_search
{
    "post_filter": {
        "term": {
            "itemID": "ID100123"  # 这里无法查询出来,因为itemId是text类型会被分词,分词后存
储为小写,所以这里有2种处理办法,第一种,把id改为小写:id100123,第二种设置字段index:false
          }
      }
}

# 查看分词器分析的结果,不希望商品id字段被分词,则重新创建映射
# GET /lib4/_mapping

DELETE lib4

PUT /lib4
{
    "mappings": {
        "items": {
            "properties": {
                "itemID": {
                    "type": "text",
                    "index": false
                }
            }
        }
    }
}




# bool过滤查询可以实现组合过滤查询
{
    "bool": {
        "must": [],
        "should": [],
        "must_not": []
    }
}
# must:必须满足的条件—and
# filter 不must不同,filter分值被忽略,过滤器字句在过滤器上下文执行,
# should:可以满足也可以不满足的条件–or
# must_not:不需要满足的条件–not

GET /lib4/items/_search
{
    "post_filter": {
          "bool": {
               "should": [
                    {"term": {"price":25}},
                    {"term": {"itemID": "id100123"}}
                   
                  ],
                "must_not": {
                    "term":{"price": 30}
                   }
                       
                }
             }
}

GET /lib4/items/_search
{
    "post_filter": {
          "bool": {
                "should": [
                    {"term": {"itemID": "id100123"}},
                    {
                      "bool": {
                          "must": [
                              {"term": {"itemID": "id100124"}},
                              {"term": {"price": 40}}
                            ]
                          }
                    }
                  ]
                }
            }
}


# 范围过滤
# gt: >     lt: <     gte: >=     lte: <=
GET /lib4/items/_search
{
     "post_filter": {
          "range": {
              "price": {
                   "gt": 25,
                   "lt": 50
                }
            }
      }
}

GET /lib4/items/_search
{
  "query": {
    "bool": {
      "filter": {
          "exists":{
             "field":"price"
         }
      }
    }
  }
}

# 过滤非空
GET /lib4/items/_search
{
    "query" : {
        "constant_score" : {
            "filter": {
                "exists" : { "field" : "price" }
            }
        }
    }
}




# 过滤器缓存
# ElasticSearch提供了一种特殊的缓存,即过滤器缓存(filter cache),用来存储过滤器的结果,被缓
# 的过滤器并不需要消耗过多的内存(因为它们只存储了哪些文档能与过滤器相匹配的相关信息),而且可供
# 后续所有与之相关的查询重复使用,从而极大地提高了查询性能。

# 注意:ElasticSearch并不是默认缓存所有过滤器

以下过滤器默认不缓存:
numeric_range
script
geo_bbox
geo_distance
geo_distance_range
geo_polygon
geo_shape
and
or
not

以下默认是开启缓存:
exists,missing,range,term,terms

# 开启方式:在filter查询语句后边加上
"_catch":true



# 聚合查询

# sum
GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_of_sum": {
         "sum": {
           "field": "price"
         }
     }
  }
}

#min
GET /lib4/items/_search
{
  "size": 0, 
  "aggs": {
     "price_of_min": {
         "min": {
           "field": "price"
         }
     }
  }
}


# max
GET /lib4/items/_search
{
  "size": 0, 
  "aggs": {
     "price_of_max": {
         "max": {
           "field": "price"
         }
     }
  }
}


# avg
GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_of_avg": {
         "avg": {
           "field": "price"
         }
     }
  }
}


# cardinality:求基数,互不相同的数,类似distinct,不包含null。(null,1,2,3,基数为3)
GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_of_cardi": {
         "cardinality": {
           "field": "price"
         }
     }
  }
}


# terms:分组
GET /lib4/items/_search
{
  "size":0,
  "aggs": {
     "price_group_by": {
         "terms": {
           "field": "price"
         }
     }
  }
}


# 对那些有唱歌兴趣的用户按年龄分组
GET /lib3/user/_search
{
  "query": {
      "match": {
        "interests": "changge"
      }
   },
   "size": 0, 
   "aggs":{
       "age_group_by":{
           "terms": {
             "field": "age",
             "order": {
               "avg_of_age": "desc"
             }
           },
           "aggs": {
             "avg_of_age": {
               "avg": {
                 "field": "age"
               }
             }
           }
       }
   }
}

 

基于groovy脚本执行partial update

es有内置的脚本支持,可以基于groovy脚本实现复杂的操作

# 修改年龄
POST /lib/user/4/_update
{
  "script": "ctx._source.age+=1"
}



# 修改名字
POST /lib/user/4/_update
{
  "script": "ctx._source.last_name+='hehe'"
}



# 添加爱好
POST /lib/user/4/_update
{
  "script": {
    "source": "ctx._source.interests.add(params.tag)",
    "params": {
      "tag":"picture"
    }
  }
}



# 删除爱好
POST /lib/user/4/_update
{
  "script": {
    "source": "ctx._source.interests.remove(ctx._source.interests.indexOf(params.tag))",
    "params": {
      "tag":"picture"
    }
  }
}



# 删除文档
POST /lib/user/4/_update
{
  "script": {
    "source": "ctx.op=ctx._source.age==params.count?'delete':'none'",
    "params": {
        "count":29   # 如果这里是数值类型,不要加引号
    }
  }
}



# upsert (如果存在执行script,如果不存在则,插入更新)
POST /lib/user/4/_update
{
  "script": "ctx._source.age += 1",

  "upsert": {
     "first_name" : "Jane",
     "last_name" :   "Lucy",
     "age" :  20,
     "about" :       "I like to collect rock albums",
     "interests":  [ "music" ]
  }
}
<dependency>    
           <groupId>org.springframework.data</groupId>    
            <artifactId>spring-data-elasticsearch</artifactId>    
            <version>2.0.2.RELEASE</version>    
</dependency> 

版本对应 

ES

使用的方式主要两种:

① 一种是经过 SpringData 封装过的,直接在 dao 接口继承 ElasticsearchRepository 即可
② 一种是经过 Spring 封装过的,直接在 Service/Controller 中引入该 bean 即可

相关文章: