简介
类比mysql等关系型数据库,elasticsearch这种nosql的搜索引擎效率更快,通常的案例有百度淘宝等即时搜索功能
Relational DB -> Databases -> Tables -> Rows -> Columns
关系型数据库 数据库 表 行 列
Elasticsearch -> Indices -> Types -> Documents -> Fields
Elasticsearch 索引 类型 文档 域(字段)
elasticsearch安装(windows)
- 上官网下载压缩包
- 解压缩
- 运行
bin
目录下的elasticsearch.bat
批处理文件
- cd到对应目录在dos命令行
elasticsearch-service.bat install
安装elasticsearch
服务
- 访问
localhost:9200
(默认端口)
kibana可视化工具安装(windows)
- 上官网下载压缩包
- 解压缩
- 运行
bin
目录下的kibana.bat
(git-bash可用cmd.exe /C kibana
运行)
- 访问
localhost:5601
(默认端口)
elasticsearch在java中的使用方式
RestHighLevelClient的使用
RestHighLevelClient
即是Elasticsearch的一个高级客户端,对Elasticsearch集群的所有操作都要经过该客户端来操作。其在java中可通过低级客户端RestClient
来获得。
public RestHighLevelClient(RestClientBuilder restClientBuilder) { this(restClientBuilder, Collections.emptyList()); }
|
对索引Index的操作
创建索引
在elasticsearch
中索引就是类似数据库的结构,我们可通过创建一个CreateIndexRequest
,让客户端来执行创建请求
CreateIndexRequest request=new CreateIndexRequest("new_index"); CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
|
同时也可对CreateIndexRequest
的各种设置参数的方法来对所创建的索引结构进行设置(如分词器,过滤器等),此处不再一一说明。
判断索引是否存在
public boolean existIndex(String index) { GetIndexRequest request=new GetIndexRequest(index); try { return client.indices().exists(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return false; }
|
删除索引
public boolean deleteIndex(String index) { if(!existIndex(index)){ return false; } DeleteIndexRequest request=new DeleteIndexRequest(index); try { AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT); return response.isAcknowledged(); } catch (IOException e) { e.printStackTrace(); } return false; }
|
对文档Document的操作
文档document
类比数据库中的行,元组,通常搜索出来的元数据结果就是以每个文档为单位。每个文档都有特定的id
,所以以下与特定文档相关的方法都会包含id
这个参数
创建文档
public boolean createDocument(String index, String id, String content) { if(existDocument(index,id)){ return false; } IndexRequest request=new IndexRequest(index).id(id); request.source(content, XContentType.JSON); IndexResponse response = null; try { response = client.index(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return (response.status()==RestStatus.CREATED); }
|
判断文档是否存在
public boolean existDocument(String index, String id){ GetRequest request=new GetRequest(index,id); try { return client.exists(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return false; }
|
获取文档
public String getDocument(String index, String id) { GetRequest request=new GetRequest(index,id); GetResponse response = null; try { response = client.get(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return response.getSourceAsString(); }
|
更新文档
public boolean updateDocument(String index, String id, String content) { if(!existDocument(index,id)){ return false; } UpdateRequest request=new UpdateRequest(index,id); request.doc(content,XContentType.JSON); UpdateResponse response = null; try { response = client.update(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return (response.status()==RestStatus.OK); }
|
删除文档
public boolean deleteDocument(String index, String id) { if(!existDocument(index,id)){ return false; } DeleteRequest request=new DeleteRequest(index,id); DeleteResponse response = null; try { response = client.delete(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } return (response.status()==RestStatus.OK); }
|
批量操作
我们可以通过BulkRequest
来对多个DocWriteRequest
(DeleteRequest
,IndexRequest
,UpdateRequest
)操作进行添加集成,然后统一让RestHighLevelClient
执行对文档的批量操作,下面封装了一个进行批量操作的方法
public boolean bulkRequest(String index, Iterable<DocWriteRequest<?>> requests) { BulkRequest bulkRequest=new BulkRequest(); requests.forEach(x->{ bulkRequest.add(x); }); BulkResponse responses = null; try { responses = client.bulk(bulkRequest, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } BulkItemResponse[] items = responses.getItems(); for(BulkItemResponse tmp:items){ System.out.println("操作:"+tmp.getOpType().name()+"-主键id:"+tmp.getId()+"-是否成功:"+(!tmp.isFailed())); } return !responses.hasFailures(); }
|
使用用例
@Test void testBulkOperation(){ IndexRequest indexRequest=new IndexRequest("desktop").id("testId") .source(XContentType.JSON,"testField1","testField1"); JSONObject jsonObject=new JSONObject(); jsonObject.put("programId","5"); jsonObject.put("programName","网易云音乐-updated"); UpdateRequest updateRequest=new UpdateRequest("desktop","1006") .doc(jsonObject.toJSONString(),XContentType.JSON); List<DocWriteRequest<?>>requests=new ArrayList<>(); requests.add(indexRequest); requests.add(updateRequest); System.out.println(service.bulkRequest("desktop",requests)); }
|
对多个索引中特定的字段进行关键字查找
public List<JSONObject> searchByKeyword(String keyword,String...indices) { List<JSONObject>results=null; SearchRequest request=new SearchRequest(); request.indices(indices); SearchSourceBuilder builder=new SearchSourceBuilder(); builder.query(QueryBuilders.multiMatchQuery(keyword,"programName","tag","username") .fuzziness(Fuzziness.AUTO)); request.source(builder); SearchResponse response = null; try { response = client.search(request, RequestOptions.DEFAULT); } catch (IOException e) { e.printStackTrace(); } SearchHit[] hits = response.getHits().getHits(); if(hits.length>0){ results=new ArrayList<>(); for(SearchHit hit:hits){ JSONObject jsonObject=JSONObject.parseObject(hit.getSourceAsString()); results.add(jsonObject); } } return results; }
|
使用账号密码连接elasticsaerch
通常默认情况下es本地是不设账号密码的,可直接通过localhost:9200访问,但是也可以设置密码来加强es的安全性
修改elasticsearch.yml配置文件
使用xpack给es添加安全支持,同时允许http
请求跨域,在elasticsearch.yml
文件中添加以下配置
http.cors.enabled: true http.cors.allow-origin: "*" http.cors.allow-headers: Authorization xpack.security.enabled: true xpack.security.transport.ssl.enabled: true
|
执行自定义密码的命令
cd到es的bin
目录下,执行elasticsearch-setup-passwords interactive
,按照提示分别给几个系统都设置密码
通过kibana或localhost:9200访问测试
启动kibana/elasticsearch服务,在访问lcalhost:5601/localhost:9200
时输入es账号密码,默认账号为elastic
修改密码的curl命令
POST /_security/user/{username}/_password { "password": "your password" }
|
在Java中通过api连接
我们通常使用的是RestHighLevelClient
,其可通过低级客户端的构造器RestClientBuilder
获得,根据官方文档的指引,我们可通过设置http客户端的配置来设置账号密码最后构建RestClientBuilder
@Bean public RestClientBuilder restClientBuilder(){ final CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); RestClientBuilder builder=RestClient.builder(new HttpHost(host,port,protocol)); builder.setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) { httpAsyncClientBuilder.disableAuthCaching(); return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider); } }); return builder; }
@Bean(name = "restHighLevelClient") public RestHighLevelClient restHighLevelClient(@Autowired RestClientBuilder restClientBuilder){ return new RestHighLevelClient(restClientBuilder); }
|