一、认识
ElasticSearch以下简称ES
ES的索引库管理支持依然是基于Apache Lucene(TM)的开源搜索引擎。
ES也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTfulAPI来隐藏Lucene的复杂性,从而让全文搜索变得简单。
ES即为了解决原生Lucene使用的不足,优化Lucene的调用方式,并实现了高可用的分布式集群的搜索方案.
二、特点
分布式的实时文件存储,每个字段都被索引并可被搜索
分布式的实时分析搜索引擎
可以扩展到上百台服务器,处理PB级结构化或非结构化数据
高度集成化的服务,你的应用可以通过简单的 RESTful API、各种语言的客户端甚至命令行与之交互。
上手Elasticsearch非常容易。
三、安装
1.服务器
ES服务只依赖于JDK,推荐使用JDK1.7+
官方下载地址:https://www.elastic.co/downloads/elasticsearch
运行:bin/elasticsearch.bat
验证:http://localhost:9200/
2.客户端
运行:bin/kibana.bat
验证:http://localhost:5601/
四、Restful风格
Restful是一种面向资源的架构风格,可以简单理解为:使用URL定位资源,用HTTP动词(GET,POST,DELETE,PUT)描述操作。
好处:
透明性,暴露资源存在。
充分利用 HTTP 协议本身语义。
无状态,这点非常重要。在调用一个接口(访问、操作资源)的时候,可以不用考虑上下文,不用考虑当前状态,极大的降低了复杂度。
使用:
GET 用来获取资源,
POST 用来新建资源(也可以用于更新资源),
PUT 用来更新资源,
DELETE 用来删除资源。
比如:
GET http://api.susu.cn/emp/323 获取一个员工
POST http://api.susu.cn/emp/232: 添加或修改一个员工
PUT http://api.susu.cn/emp: 修改员工资料
DELETE http://api.susu.cn/emp/323: 删除323号员工
五、ES数据管理
1.格式:#操作 /index/type/id
2.操作:可以进行添加(POST)、修改(PUT)、删除(DELETE)、查询(GET)
、批量插入(_bulk)、批量获取(_mget)
3.分词器需要在service的plugins导入响应插件
1 # 添加 2 POST /su/i 3 { 4 "name":"s", 5 "age":19 6 } 7 8 9 # 添加 没有id就会自定创建id AWpYzIuNusgdrtR9QSb4 10 POST /su/l 11 { 12 "name":"u", 13 "age":18 14 } 15 16 # =======================修改================================= 17 18 # 修改 需要传入id 19 PUT /su/l/AWpYzIuNusgdrtR9QSb4 20 { 21 "name":"o", 22 "age":19 23 } 24 25 # =======================局部修改============================= 26 27 # 局部修改 用post _update 28 POST /su/l/AWpYzIuNusgdrtR9QSb4/_update 29 { 30 "doc":{ 31 "name":"v" 32 } 33 } 34 35 # ============================删除============================ 36 # 删除 37 DELETE /su/i/1 38 39 # ====================批量添加================================ 40 # 批量添加 _bulk 41 # create当文档不存在时创建之。 42 # index创建新文档或替换已有文档。 43 # update局部更新文档。 44 # delete删除一个文档。 45 46 POST _bulk 47 {"create":{"_index":"su","_type":"ai","_id":"1"}} 48 {"title":"我是一级标题"} 49 {"index":{"_index":"su","_type":"ai"}} 50 {"title":"我是二级标题"} 51 52 53 # =========================批量获取=========================== 54 # 批量获取 第一种方式 55 GET _mget 56 { 57 "docs":[ 58 { 59 "_index":"su", 60 "_type":"ai", 61 "_id":"1" 62 },{ 63 "_index":"su", 64 "_type":"ai", 65 "_id":"AWpZFxJqusgdrtR9QScB" 66 } 67 ] 68 } 69 70 # 批量获取 第二种方式 _mget 71 GET /su/ai/_mget 72 { 73 "ids":["1","AWpZFxJqusgdrtR9QScB"] 74 } 75 76 # =======================普通查询============================= 77 # 查询source里面的数据 78 GET /su/i/1/_source 79 # 查询全部 80 GET _search 81 82 # ==========================分页搜索========================== 83 # 分页搜索 84 # size : 每页条数,默认 10 85 # from : 从第几条开始,默认 0 86 87 # 查询2条 从第一条开始 88 GET _search?size=2 89 # 查询3条 从第二条开始 90 GET _search?size=3&from=1 91 # 查询3条 从第一条开始 92 GET _search?size=3&from=0 93 94 # ===================条件搜索================================= 95 # 条件搜索 96 # 年龄段 age[20 TO 30] 97 # 查询年龄等于19的 98 GET /su/l/_search?q=age:19 99 # 查询年龄等于19的 并且名字为 v 的 100 GET /su/l/_search?q=age:19+name:v 101 102 # =========================DSL查询============================ 103 # DSL查询 104 # 由ES提供丰富且灵活的查询语言 105 GET /su/i/_search 106 { 107 "query": { 108 "match": { 109 "name": "s" 110 } 111 }, 112 "from": 0, 113 "size": 3, 114 "_source": ["name"], 115 "sort": [ 116 { 117 "age": { 118 "order": "asc" 119 } 120 } 121 ] 122 123 } 124 125 # =======================过滤================================= 126 # DSL过滤 127 # 与(must) 或(should) 非(must not) 128 GET /su/i/_search 129 { 130 "query": { 131 "bool": { 132 "must": [ 133 {"term": { 134 "name": { 135 "value": "s" 136 } 137 }} 138 ], 139 "filter": { 140 "term": { 141 "age": "18" 142 } 143 } 144 } 145 146 } 147 } 148 149 # =======================分词================================= 150 # 分词 151 POST _analyze 152 { 153 "analyzer": "ik_smart", 154 "text": "他日若遂凌云志敢笑黄巢不丈夫" 155 }
六、文档映射
ES的文档映射(mapping)机制用于进行字段类型确认,将每个字段匹配为一种确定的数据类型。(相当于写表结构)
基本字段类型
字符串:text(分词),keyword(不分词) StringField(不分词文本),TextFiled(要分词文本) text默认为全文文本,keyword默认为非全文文本
数字:long,integer,short,double,float
日期:date
逻辑:boolean
复杂数据类型
对象类型:object
数组类型:array
地理位置:geo_point,geo_shape
注意:
你可以向已有映射中增加字段,但你不能修改它。如果一个字段在映射中已经存在,这可能意味着那个字段的数据已经被索引。如果你改变了字段映射,那已经被索引的数据将错误并且不能被正确的搜索到。
我们可以更新一个映射来增加一个新字段,但是不能把已有字段的类型那个从 analyzed 改到 not_analyzed。
七、javaAPI
1.导包
1 <dependency> 2 <groupId>org.elasticsearch.client</groupId> 3 <artifactId>transport</artifactId> 4 <version>5.2.2</version> 5 </dependency> 6 <dependency> 7 <groupId>org.apache.logging.log4j</groupId> 8 <artifactId>log4j-api</artifactId> 9 <version>2.7</version> 10 </dependency> 11 <dependency> 12 <groupId>org.apache.logging.log4j</groupId> 13 <artifactId>log4j-core</artifactId> 14 <version>2.7</version> 15 </dependency> 16 <dependency> 17 <groupId>junit</groupId> 18 <artifactId>junit</artifactId> 19 <version>4.12</version> 20 <scope>compile</scope> 21 </dependency>
2.代码
1 public class TestEs { 2 3 //拿到es对象 4 public static TransportClient getClient() throws Exception { 5 TransportClient client = new PreBuiltTransportClient(Settings.EMPTY). 6 addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 7 9300)); 8 return client; 9 } 10 11 //创建数据 12 @Test 13 public void testIndex() throws Exception{ 14 TransportClient client = getClient(); 15 //创建索引库 16 IndexRequestBuilder indexRequestBuilder = client.prepareIndex("su","l","1"); 17 //准备数据 18 Map mp = new HashMap<>(); 19 mp.put("id", 1); 20 mp.put("name", "s"); 21 mp.put("age", 18); 22 IndexResponse indexResponse = indexRequestBuilder.setSource(mp).get(); 23 System.out.println(indexResponse); 24 25 } 26 27 //查询数据 28 @Test 29 public void testGet() throws Exception{ 30 TransportClient client = getClient(); 31 GetResponse getFields = client.prepareGet("su", "l", "1").get(); 32 System.out.println(getFields.getSource());//{name=s, id=1, age=18} 33 34 } 35 36 //修改数据 37 @Test 38 public void testUpdate() throws Exception{ 39 TransportClient client = getClient(); 40 HashMap mp = new HashMap(); 41 mp.put("id", 2); 42 mp.put("name", "u"); 43 mp.put("age", 19); 44 //必须 .get取到值 45 UpdateResponse updateResponse = client.prepareUpdate("su", "l", "1").setDoc(mp).get(); 46 GetResponse getFields = client.prepareGet("su", "l", "1").get(); 47 System.out.println(getFields.getSource());//{name=u, id=2, age=19} 48 } 49 50 //删除数据 51 @Test 52 public void testDelete() throws Exception{ 53 TransportClient client = getClient(); 54 //必须 .get取到值 55 client.prepareDelete("su", "l", "1").get(); 56 GetResponse getFields = client.prepareGet("su", "l", "1").get(); 57 System.out.println("--"+getFields.getSource());//--null 58 } 59 60 //批量插入 61 @Test 62 public void testBulk() throws Exception{ 63 TransportClient client = getClient(); 64 BulkRequestBuilder bulkRequestBuilder = client.prepareBulk(); 65 for (int i=1;i<=10;i++){ 66 Map mp =new HashMap(); 67 mp.put("id",i ); 68 mp.put("name", "ss"+i); 69 mp.put("age", 10+i); 70 mp.put("class", 1); 71 bulkRequestBuilder.add(client.prepareIndex("crm","classes",i+"").setSource(mp)); 72 } 73 BulkResponse bulkItemResponses = bulkRequestBuilder.get(); 74 if(bulkItemResponses.hasFailures()){ 75 System.out.println("error"); 76 } 77 client.close(); 78 } 79 80 @Test 81 public void testQuery() throws Exception{ 82 TransportClient client = getClient(); 83 BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); 84 85 //搜索 86 List<QueryBuilder> must = boolQueryBuilder.must(); 87 must.add(QueryBuilders.termQuery("class", 1)); 88 89 //过滤 90 List<QueryBuilder> filter = boolQueryBuilder.filter(); 91 filter.add(QueryBuilders.rangeQuery("age").gte(13).lte(16)); 92 93 //分页0,3 94 SearchResponse searchResponse = client.prepareSearch("crm").setFrom(1).setSize(3). 95 setQuery(boolQueryBuilder).addSort("age", SortOrder.DESC).get(); 96 97 System.out.println("总共命中条数:"+searchResponse.getHits().getTotalHits()); 98 SearchHit[] hits = searchResponse.getHits().getHits(); 99 for (SearchHit hit : hits) { 100 System.out.println(hit.getSource()); 101 } 102 client.close(); 103 } 104 }