ElasticSearch是开源搜索平台的新成员,实时数据分析的神器。可以理解为作为搜索的数据库,可以提供搜索功能。对比关系型数据库,具有以下的相似关系:

关系型数据库 数据库
ElasticSearch 索引 类型 文档 字段

  一个ES集群可以包含多个索引(数据库),每个索引又包含了很多类型(表),类型中包含了很多文档(行),每个文档又包含了很多字段(列)。

  如果要实现对关系型数据库数据的搜索功能,需要将关系型数据库中的数据导入到ElasticSearch中,网上有解决方案。但是好像不支持最新的ElasticSearch5,可以使用我下面的Java代码实现数据的导入。

Ubuntu系统安装 Elasticsearch5

升级系统后安装 Oracle Java 7,既然 Elasticsearch 官方推荐使用 Oracle JDK 7 就不要尝试 JDK 8 和 OpenJDK 了:

  1. 1 $ sudo apt-get update
  2. 2 $ sudo apt-get upgrade
  3. 3
  4. 4 $ sudo apt-get install software-properties-common
  5. 5 $ sudo add-apt-repository ppa:webupd8team/java
  6. 6 $ sudo apt-get update
  7. 7
  8. 8 $ sudo apt-get install oracle-java7-installer

加入 Elasticsearch 官方源后安装 elasticsearch:

  1. 1 $ wget -O - http://packages.elasticsearch.org/GPG-KEY-elasticsearch | apt-key add -
  2. 2 $ sudo echo "deb http://packages.elasticsearch.org/elasticsearch/1.1/debian stable main" >> /etc/apt/sources.list
  3. 3
  4. 4 $ sudo apt-get update
  5. 5 $ sudo apt-get install elasticsearch

加入到系统启动文件并启动 elasticsearch 服务,用 curl 测试一下安装是否成功:

  1. 1 $ sudo update-rc.d elasticsearch defaults 95 1
  2. 2
  3. 3 $ sudo /etc/init.d/elasticsearch start
  4. 4
  5. 5 $ curl -X GET 'http://localhost:9200'
  6. 6 {
  7. 7 "status" : 200,
  8. 8 "name" : "Fer-de-Lance",
  9. 9 "version" : {
  10. 10 "number" : "1.1.1",
  11. 11 "build_hash" : "f1585f096d3f3985e73456debdc1a0745f512bbc",
  12. 12 "build_timestamp" : "2014-04-16T14:27:12Z",
  13. 13 "build_snapshot" : false,
  14. 14 "lucene_version" : "4.7"
  15. 15 },
  16. 16 "tagline" : "You Know, for Search"
  17. 17 }

Elasticsearch 的集群和数据管理界面 Marvel 非常赞,可惜只对开发环境免费,安装很简单,完成后重启服务访问 http://192.168.2.172:9200/_plugin/marvel/ 就可以看到界面:

  1. 1 $ sudo /usr/share/elasticsearch/bin/plugin -i elasticsearch/marvel/latest
  2. 2
  3. 3 $ sudo /etc/init.d/elasticsearch restart
  4. 4 * Stopping Elasticsearch Server [ OK ]
  5. 5 * Starting Elasticsearch Server [ OK ]

另外可以安装elasticsearch-head作为管理Elasticsearch的web前端插件。

安装教程:Elasticsearch5中安装Elasticsearch-head插件

ElasticSearch Java调用

  命令调用的方式不再讲述了,网上很多。ElasticSearch最终是要在项目中使用的。官方的API文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

自己写了助手类,方便大家调用。可以实现索引的增删改查,查询提供多种方法,包括or、and查询,多个关键词查询,关键词高亮等,适用于不同场合。

首先是引用需要的jar包。使用maven管理jar包,需要的jar包有:

  1. 1 <dependency>
  2. 2 <groupId>org.elasticsearch</groupId>
  3. 3 <artifactId>elasticsearch</artifactId>
  4. 4 <version>5.3.1</version>
  5. 5 </dependency>
  6. 6 <dependency>
  7. 7 <groupId>org.elasticsearch.client</groupId>
  8. 8 <artifactId>transport</artifactId>
  9. 9 <version>5.3.1</version>
  10. 10 </dependency>
  11. 11 <dependency>
  12. 12 <groupId>org.apache.logging.log4j</groupId>
  13. 13 <artifactId>log4j-api</artifactId>
  14. 14 <version>2.7</version>
  15. 15 </dependency>
  16. 16 <dependency>
  17. 17 <groupId>org.apache.logging.log4j</groupId>
  18. 18 <artifactId>log4j-core</artifactId>
  19. 19 <version>2.7</version>
  20. 20 </dependency>

然后是ElasticSearch配置文件,存储集群名称、集群IP、索引名称。配置文件命名为:elasticsearch.properties

  1. cluster_name=elasticsearch
  2. cluster_serverip=127.0.0.1
  3. indexname=blogsystem

还需要配置日志配置文件,命名为:log4j2.properties

  1. appender.console.type = Console
  2. appender.console.name = console
  3. appender.console.layout.type = PatternLayout
  4.  
  5. rootLogger.level = info
  6. rootLogger.appenderRef.console.ref = console

最后是java的实现ElasticSearch助手类。为了方便使用,助手类分为具体实现和调用两个类。

ElasticSearch具体实现类:ElasticSearchUtilsImp.java

  1. package com.blog.utils;
  2.  
  3. import java.io.IOException;
  4. import java.io.InputStream;
  5. import java.lang.reflect.Method;
  6. import java.net.InetAddress;
  7. import java.net.UnknownHostException;
  8. import java.util.ArrayList;
  9. import java.util.HashMap;
  10. import java.util.List;
  11. import java.util.Map;
  12. import java.util.Properties;
  13. import java.util.concurrent.ExecutionException;
  14.  
  15. import org.elasticsearch.action.delete.DeleteResponse;
  16. import org.elasticsearch.action.index.IndexResponse;
  17. import org.elasticsearch.action.search.SearchRequestBuilder;
  18. import org.elasticsearch.action.search.SearchResponse;
  19. import org.elasticsearch.action.update.UpdateRequest;
  20. import org.elasticsearch.client.transport.TransportClient;
  21. import org.elasticsearch.common.settings.Settings;
  22. import org.elasticsearch.common.text.Text;
  23. import org.elasticsearch.common.transport.InetSocketTransportAddress;
  24. import org.elasticsearch.common.xcontent.XContentBuilder;
  25. import org.elasticsearch.common.xcontent.XContentFactory;
  26. import org.elasticsearch.index.query.BoolQueryBuilder;
  27. import org.elasticsearch.index.query.QueryBuilder;
  28. import org.elasticsearch.index.query.QueryBuilders;
  29. import org.elasticsearch.rest.RestStatus;
  30. import org.elasticsearch.search.SearchHits;
  31. import org.elasticsearch.search.aggregations.AggregationBuilders;
  32. import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
  33. import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
  34. import org.elasticsearch.transport.client.PreBuiltTransportClient;
  35.  
  36. /**
  37. * @author:Tim
  38. * @date:2017年5月3日 下午8:24:22
  39. * @description:ElasticSearch助手类具体实现
  40. */
  41. public class ElasticSearchUtilsImp {
  42.  
  43. private static String cluster_name = null;// 实例名称
  44. private static String cluster_serverip = null;// elasticSearch服务器ip
  45. private static String indexname = null;// 索引名称
  46.  
  47. static {
  48. try {
  49. // 读取db.properties文件
  50. Properties props = new Properties();
  51. InputStream in = ElasticSearchUtilsImp.class.getResourceAsStream("/elasticsearch.properties");
  52. props.load(in);// 加载文件
  53.  
  54. // 读取信息
  55. cluster_name = props.getProperty("cluster_name");
  56. cluster_serverip = props.getProperty("cluster_serverip");
  57. indexname = props.getProperty("indexname");
  58. } catch (IOException e) {
  59. e.printStackTrace();
  60. System.out.println("加载数据库配置文件出错!");
  61. }
  62. }
  63.  
  64. /**
  65. * 返回一个到ElasticSearch的连接客户端
  66. *
  67. * @return
  68. */
  69. private static TransportClient getClient() {
  70. Settings settings = Settings.builder().put("cluster.name", cluster_name).build();// 设置集群名称
  71. @SuppressWarnings("unchecked")
  72. TransportClient client = new PreBuiltTransportClient(settings);// 创建client
  73. try {
  74. client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(cluster_serverip), 9300));// 增加地址和端口
  75. } catch (UnknownHostException e) {
  76. e.printStackTrace();
  77. System.out.println("ElasticSearch连接失败!");
  78. }
  79.  
  80. return client;
  81. }
  82.  
  83. /**
  84. * 将Map转换成builder
  85. *
  86. * @param mapParam
  87. * @return
  88. * @throws Exception
  89. */
  90. private static XContentBuilder createMapJson(Map<String, String> mapParam) throws Exception {
  91. XContentBuilder source = XContentFactory.jsonBuilder().startObject();
  92.  
  93. for (Map.Entry<String, String> entry : mapParam.entrySet()) {
  94. source.field(entry.getKey(), entry.getValue());
  95. }
  96.  
  97. source.endObject();
  98.  
  99. return source;
  100. }
  101.  
  102. /**
  103. * 将实体转换成json
  104. *
  105. * @param entity 实体
  106. * @param fieldNameParm 实体中待转换成json的字段
  107. * @return 返回json
  108. * @throws Exception
  109. */
  110. private static XContentBuilder createEntityJson(Object entity, String... methodNameParm) throws Exception {
  111. // 创建json对象, 其中一个创建json的方式
  112. XContentBuilder source = XContentFactory.jsonBuilder().startObject();
  113.  
  114. try {
  115. for (String methodName : methodNameParm) {
  116.  
  117. if (!methodName.startsWith("get")) {
  118. throw new Exception("不是有效的属性!");
  119. }
  120.  
  121. Method method = entity.getClass().getMethod(methodName, null);
  122. String fieldValue = (String) method.invoke(entity, null);
  123. String fieldName = StringUtils.toLowerCaseFirstOne(methodName.replace("get", ""));// 去掉“get”,并将首字母小写
  124.  
  125. // 避免和elasticSearch中id字段重复
  126. if (fieldName == "_id") {
  127. fieldName = "id";
  128. }
  129.  
  130. source.field(fieldName, fieldValue);
  131. }
  132. } catch (NoSuchMethodException e) {
  133. e.printStackTrace();
  134. System.out.println("未找到方法!");
  135. }
  136.  
  137. source.endObject();
  138.  
  139. return source;
  140. }
  141.  
  142. /**
  143. * 将一个Map格式的数据(key,value)插入索引 (私有方法)
  144. *
  145. * @param type 类型(对应数据库表)
  146. * @param docId id,对应elasticSearch中的_id字段
  147. * @param mapParam Map格式的数据
  148. * @return
  149. */
  150. public static boolean addMapDocToIndex(String type, String docId, Map<String, String> mapParam) {
  151. boolean result = false;
  152.  
  153. TransportClient client = getClient();
  154. XContentBuilder source = null;
  155. try {
  156. source = createMapJson(mapParam);
  157. } catch (Exception e) {
  158. e.printStackTrace();
  159. }
  160.  
  161. // 存json入索引中
  162. IndexResponse response = null;
  163. if (docId == null) {
  164. // 使用默认的id
  165. response = client.prepareIndex(indexname, type).setSource(source).get();
  166. } else {
  167. response = client.prepareIndex(indexname, type, docId).setSource(source).get();
  168. }
  169.  
  170. // 插入结果获取
  171. String index = response.getIndex();
  172. String gettype = response.getType();
  173. String id = response.getId();
  174. long version = response.getVersion();
  175. RestStatus status = response.status();
  176.  
  177. String strResult = "新增文档成功:" + index + " : " + gettype + ": " + id + ": " + version + ": " + status.getStatus();
  178. System.out.println(strResult);
  179.  
  180. if (status.getStatus() == 201) {
  181. result = true;
  182. }
  183.  
  184. // 关闭client
  185. client.close();
  186.  
  187. return result;
  188. }
  189.  
  190. /**
  191. * 将一个实体存入到默认索引的类型中(指定_id,一般是业务数据的id,及elasticSearch和关系型数据使用同一个id,方便同关系型数据库互动)
  192. * (私有方法)
  193. *
  194. * @param type 类型(对应数据库表)
  195. * @param docId id,对应elasticSearch中的_id字段
  196. * @param entity 要插入的实体
  197. * @param methodNameParm 需要将实体中哪些属性作为字段
  198. * @return
  199. */
  200. public static boolean addEntityDoc(String type, String docId, Object entity, String... methodNameParm) {
  201. boolean result = false;
  202.  
  203. TransportClient client = getClient();
  204. XContentBuilder source = null;
  205. try {
  206. source = createEntityJson(entity, methodNameParm);
  207. } catch (Exception e) {
  208. e.printStackTrace();
  209. }
  210.  
  211. // 存json入索引中
  212. IndexResponse response = null;
  213. if (docId == null) {
  214. // 使用默认的id
  215. response = client.prepareIndex(indexname, type).setSource(source).get();
  216. } else {
  217. response = client.prepareIndex(indexname, type, docId).setSource(source).get();
  218. }
  219.  
  220. // 插入结果获取
  221. String index = response.getIndex();
  222. String gettype = response.getType();
  223. String id = response.getId();
  224. long version = response.getVersion();
  225. RestStatus status = response.status();
  226.  
  227. String strResult = "新增文档成功:" + index + " : " + gettype + ": " + id + ": " + version + ": " + status.getStatus();
  228. System.out.println(strResult);
  229.  
  230. if (status.getStatus() == 201) {
  231. result = true;
  232. }
  233.  
  234. // 关闭client
  235. client.close();
  236.  
  237. return result;
  238. }
  239.  
  240. /**
  241. * 删除文档
  242. *
  243. * @param type 类型(对应数据库表)
  244. * @param docId 类型中id
  245. * @return
  246. */
  247. public static boolean deleteDoc(String type, String docId) {
  248. boolean result = false;
  249.  
  250. TransportClient client = getClient();
  251. DeleteResponse deleteresponse = client.prepareDelete(indexname, type, docId).get();
  252.  
  253. System.out.println("删除结果:" + deleteresponse.getResult().toString());
  254. if (deleteresponse.getResult().toString() == "DELETED") {
  255. result = true;
  256. }
  257.  
  258. // 关闭client
  259. client.close();
  260.  
  261. return result;
  262. }
  263.  
  264. /**
  265. * 修改文档
  266. *
  267. * @param type 类型
  268. * @param docId 文档id
  269. * @param updateParam 需要修改的字段和值
  270. * @return
  271. */
  272. public static boolean updateDoc(String type, String docId, Map<String, String> updateParam) {
  273. String strResult = "";
  274. boolean result = false;
  275.  
  276. TransportClient client = getClient();
  277.  
  278. UpdateRequest updateRequest = new UpdateRequest();
  279. updateRequest.index(indexname);
  280. updateRequest.type(type);
  281. updateRequest.id(docId);
  282. try {
  283. updateRequest.doc(createMapJson(updateParam));
  284. } catch (Exception e) {
  285. e.printStackTrace();
  286. }
  287. try {
  288. strResult = client.update(updateRequest).get().getResult().toString();
  289. } catch (InterruptedException e) {
  290. e.printStackTrace();
  291. } catch (ExecutionException e) {
  292. e.printStackTrace();
  293. }
  294. System.out.println(strResult);
  295.  
  296. if (strResult == "UPDATED") {
  297. result = true;
  298. }
  299.  
  300. return result;
  301. }
  302.  
  303. /**
  304. * TODO or查询命中条数
  305. * @param type 类型
  306. * @param shouldMap 查询条件
  307. * @return
  308. */
  309. public static int multiOrSearchDocCount(String type, Map<String, String> shouldMap) {
  310. TransportClient client = getClient();
  311.  
  312. return 0;
  313. }
  314.  
  315. /**
  316. * 高亮搜索
  317. *
  318. * @param type 类型
  319. * @param fieldName 段
  320. * @param keyword 关键词
  321. * @param from 开始行数
  322. * @param size 每页大小
  323. * @return
  324. */
  325. public static Map<String, Object> searchDocHighlight(String type, String fieldName, String keyword, int from,
  326. int size) {
  327. TransportClient client = getClient();
  328.  
  329. // 高亮
  330. HighlightBuilder hiBuilder = new HighlightBuilder();
  331. hiBuilder.preTags("<span style=\"color:red\">");
  332. hiBuilder.postTags("</span>");
  333. hiBuilder.field(fieldName);
  334.  
  335. QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery(fieldName, keyword);
  336.  
  337. SearchRequestBuilder responsebuilder = client.prepareSearch(indexname).setTypes(type);
  338. responsebuilder.setQuery(queryBuilder);
  339. responsebuilder.highlighter(hiBuilder);
  340. responsebuilder.setFrom(from);
  341. responsebuilder.setSize(size);
  342. responsebuilder.setExplain(true);
  343.  
  344. SearchResponse myresponse = responsebuilder.execute().actionGet();
  345. SearchHits searchHits = myresponse.getHits();
  346.  
  347. // 总命中数
  348. long total = searchHits.getTotalHits();
  349. Map<String, Object> map = new HashMap<String, Object>();
  350. map.put("total", total);
  351. List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
  352. for (int i = 0; i < searchHits.getHits().length; i++) {
  353. Map<String, HighlightField> highlightFields = searchHits.getHits()[i].getHighlightFields();
  354.  
  355. // 段高亮
  356. HighlightField titleField = highlightFields.get(fieldName);
  357. Map<String, Object> source = searchHits.getHits()[i].getSource();
  358. if (titleField != null) {
  359. Text[] fragments = titleField.fragments();
  360. String name = "";
  361. for (Text text : fragments) {
  362. name += text;
  363. }
  364. source.put(fieldName, name);
  365. }
  366.  
  367. list.add(source);
  368. }
  369. map.put("rows", list);
  370.  
  371. return map;
  372. }
  373.  
  374. /**
  375. * or条件查询高亮
  376. *
  377. * @param type 类型
  378. * @param shouldMap or条件和值
  379. * @param from 开始行数
  380. * @param size 每页大小
  381. * @return
  382. */
  383. public static Map<String, Object> multiOrSearchDocHigh(String type, Map<String, String> shouldMap, int from,
  384. int size) {
  385. TransportClient client = getClient();
  386.  
  387. SearchRequestBuilder responsebuilder = client.prepareSearch(indexname).setTypes(type);
  388. responsebuilder.setFrom(from);
  389. responsebuilder.setSize(size);
  390. responsebuilder.setExplain(true);
  391.  
  392. // 高亮
  393. HighlightBuilder hiBuilder = new HighlightBuilder();
  394. hiBuilder.preTags("<span style=\"color:red\">");
  395. hiBuilder.postTags("</span>");
  396.  
  397. // 高亮每个字段
  398. for (String key : shouldMap.keySet()) {
  399. hiBuilder.field(key);
  400. }
  401.  
  402. responsebuilder.highlighter(hiBuilder);
  403.  
  404. if (null != shouldMap && shouldMap.size() > 0) {
  405. // 创建一个查询
  406. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
  407.  
  408. // 这里查询的条件用map传递
  409. for (String key : shouldMap.keySet()) {
  410. queryBuilder.should(QueryBuilders.matchPhraseQuery(key, shouldMap.get(key)));// or连接条件
  411. }
  412. // 查询
  413. responsebuilder.setQuery(queryBuilder);
  414. }
  415.  
  416. SearchResponse myresponse = responsebuilder.execute().actionGet();
  417. SearchHits searchHits = myresponse.getHits();
  418.  
  419. // 总命中数
  420. long total = searchHits.getTotalHits();
  421. Map<String, Object> map = new HashMap<String, Object>();
  422. map.put("total", total);
  423. List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
  424. for (int i = 0; i < searchHits.getHits().length; i++) {
  425. Map<String, HighlightField> highlightFields = searchHits.getHits()[i].getHighlightFields();
  426. Map<String, Object> source = searchHits.getHits()[i].getSource();
  427.  
  428. for (String key : shouldMap.keySet()) {
  429. // 各个段进行高亮
  430. HighlightField titleField = highlightFields.get(key);
  431. if (titleField != null) {
  432. Text[] fragments = titleField.fragments();
  433. String name = "";
  434. for (Text text : fragments) {
  435. name += text;
  436. }
  437. source.put(key, name);
  438. }
  439. }
  440.  
  441. list.add(source);
  442. }
  443. map.put("rows", list);
  444.  
  445. return map;
  446. }
  447.  
  448. /**
  449. * 搜索
  450. *
  451. * @param type 类型
  452. * @param fieldName 待搜索的字段
  453. * @param keyword 待搜索的关键词
  454. * @param from 开始行数
  455. * @param size 每页大小
  456. * @return
  457. */
  458. public static Map<String, Object> searchDoc(String type, String fieldName, String keyword, int from, int size) {
  459. List<String> hitResult = new ArrayList<String>();
  460.  
  461. TransportClient client = getClient();
  462.  
  463. QueryBuilder queryBuilder = QueryBuilders.matchPhraseQuery(fieldName, keyword);
  464.  
  465. SearchRequestBuilder responsebuilder = client.prepareSearch(indexname).setTypes(type);
  466. responsebuilder.setQuery(queryBuilder);
  467. responsebuilder.setFrom(from);
  468. responsebuilder.setSize(size);
  469. responsebuilder.setExplain(true);
  470.  
  471. SearchResponse myresponse = responsebuilder.execute().actionGet();
  472. SearchHits hits = myresponse.getHits();
  473. for (int i = 0; i < hits.getHits().length; i++) {
  474. hitResult.add(hits.getHits()[i].getSourceAsString());
  475. }
  476.  
  477. // 将命中结果转换成Map输出
  478. Map<String, Object> modelMap = new HashMap<String, Object>(2);
  479. modelMap.put("total", hitResult.size());
  480. modelMap.put("rows", hitResult);
  481.  
  482. return modelMap;
  483. }
  484.  
  485. /**
  486. * 多个条件进行or查询
  487. *
  488. * @param type 类型
  489. * @param shouldMap 进行or查询的段和值
  490. * @param from 开始行数
  491. * @param size 每页大小
  492. * @return
  493. */
  494. public static Map<String, Object> multiOrSearchDoc(String type, Map<String, String> shouldMap, int from, int size) {
  495. List<String> hitResult = new ArrayList<String>();
  496.  
  497. TransportClient client = getClient();
  498.  
  499. SearchRequestBuilder responsebuilder = client.prepareSearch(indexname).setTypes(type);
  500. responsebuilder.setFrom(from);
  501. responsebuilder.setSize(size);
  502. responsebuilder.setExplain(true);
  503.  
  504. if (null != shouldMap && shouldMap.size() > 0) {
  505. // 创建一个查询
  506. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
  507.  
  508. // 这里查询的条件用map传递
  509. for (String key : shouldMap.keySet()) {
  510. queryBuilder.should(QueryBuilders.matchPhraseQuery(key, shouldMap.get(key)));// or连接条件
  511. }
  512. // 查询
  513. responsebuilder.setQuery(queryBuilder);
  514. }
  515.  
  516. SearchResponse myresponse = responsebuilder.execute().actionGet();
  517. SearchHits hits = myresponse.getHits();
  518. for (int i = 0; i < hits.getHits().length; i++) {
  519. hitResult.add(hits.getHits()[i].getSourceAsString());
  520. }
  521.  
  522. // 将命中结果转换成Map输出
  523. Map<String, Object> modelMap = new HashMap<String, Object>(2);
  524. modelMap.put("total", hitResult.size());
  525. modelMap.put("rows", hitResult);
  526.  
  527. return modelMap;
  528. }
  529.  
  530. /**
  531. * 多个条件进行and查询
  532. *
  533. * @param type 类型
  534. * @param mustMap 进行and查询的段和值
  535. * @param from 开始行数
  536. * @param size 每页大小
  537. * @return
  538. */
  539. public static Map<String, Object> multiAndSearchDoc(String type, Map<String, String> mustMap, int from, int size) {
  540. List<String> hitResult = new ArrayList<String>();
  541.  
  542. TransportClient client = getClient();
  543.  
  544. SearchRequestBuilder responsebuilder = client.prepareSearch(indexname).setTypes(type);
  545. responsebuilder.setFrom(from);
  546. responsebuilder.setSize(size);
  547. responsebuilder.setExplain(true);
  548.  
  549. if (null != mustMap && mustMap.size() > 0) {
  550. // 创建一个查询
  551. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
  552.  
  553. // 这里查询的条件用map传递
  554. for (String key : mustMap.keySet()) {
  555. queryBuilder.must(QueryBuilders.matchPhraseQuery(key, mustMap.get(key)));// and查询
  556. }
  557. // 查询
  558. responsebuilder.setQuery(queryBuilder);
  559. }
  560.  
  561. SearchResponse myresponse = responsebuilder.execute().actionGet();
  562. SearchHits hits = myresponse.getHits();
  563. for (int i = 0; i < hits.getHits().length; i++) {
  564. hitResult.add(hits.getHits()[i].getSourceAsString());
  565. }
  566.  
  567. // 将命中结果转换成Map输出
  568. Map<String, Object> modelMap = new HashMap<String, Object>(2);
  569. modelMap.put("total", hitResult.size());
  570. modelMap.put("rows", hitResult);
  571.  
  572. return modelMap;
  573. }
  574. }

ElasticSearchUtilsImp.java

ElasticSearch调用类,是对实现类的各种组合,供外部调用。调用类名称:ElasticSearchUtils.java

  1. 1 package com.blog.utils;
  2. 2
  3. 3 import java.util.Map;
  4. 4
  5. 5 /**
  6. 6 * @author:Tim
  7. 7 * @date:2017年5月3日 下午8:24:22
  8. 8 * @description:ElasticSearch助手类
  9. 9 */
  10. 10 public class ElasticSearchUtils {
  11. 11
  12. 12 /**
  13. 13 * 将一个Map格式的数据(key,value)插入索引(指定_id,一般是业务数据的id,及elasticSearch和关系型数据使用同一个id,方便同关系型数据库互动)
  14. 14 *
  15. 15 * @param type 类型(对应数据库表)
  16. 16 * @param docId id,对应elasticSearch中的_id字段
  17. 17 * @param mapParam Map格式的数据
  18. 18 * @return
  19. 19 */
  20. 20 public static boolean addDoc(String type, String docId, Map<String, String> mapParam) {
  21. 21 return ElasticSearchUtilsImp.addMapDocToIndex(type, docId, mapParam);
  22. 22 }
  23. 23
  24. 24 /**
  25. 25 * 将一个Map格式的数据(key,value)插入索引 (使用默认_id)
  26. 26 *
  27. 27 * @param type 类型(对应数据库表)
  28. 28 * @param mapParam Map格式的数据
  29. 29 * @return
  30. 30 */
  31. 31 public static boolean addDoc(String type, Map<String, String> mapParam) {
  32. 32 return ElasticSearchUtilsImp.addMapDocToIndex(type, null, mapParam);
  33. 33 }
  34. 34
  35. 35 /**
  36. 36 * 将一个实体存入到默认索引的类型中(默认_id)
  37. 37 *
  38. 38 * @param type 类型(对应数据库表)
  39. 39 * @param entity 要插入的实体
  40. 40 * @param methodNameParm 需要将实体中哪些属性作为字段
  41. 41 * @return
  42. 42 */
  43. 43 public static boolean addDoc(String type, Object entity, String... methodNameParm) {
  44. 44 return ElasticSearchUtilsImp.addEntityDoc(type, null, entity, methodNameParm);
  45. 45 }
  46. 46
  47. 47 /**
  48. 48 * 将一个实体存入到默认索引的类型中(指定_id,一般是业务数据的id,及elasticSearch和关系型数据使用同一个id,方便同关系型数据库互动)
  49. 49 *
  50. 50 * @param type 类型(对应数据库表)
  51. 51 * @param docId id,对应elasticSearch中的_id字段
  52. 52 * @param entity 要插入的实体
  53. 53 * @param methodNameParm 需要将实体中哪些属性作为字段
  54. 54 * @return
  55. 55 */
  56. 56 public static boolean addDoc(String type, String docId, Object entity, String... methodNameParm) {
  57. 57 return ElasticSearchUtilsImp.addEntityDoc(type, docId, entity, methodNameParm);
  58. 58 }
  59. 59
  60. 60 /**
  61. 61 * 删除文档
  62. 62 *
  63. 63 * @param type 类型(对应数据库表)
  64. 64 * @param docId 类型中id
  65. 65 * @return
  66. 66 */
  67. 67 public static boolean deleteDoc(String type, String docId) {
  68. 68 return ElasticSearchUtilsImp.deleteDoc(type, docId);
  69. 69 }
  70. 70
  71. 71 /**
  72. 72 * 修改文档
  73. 73 *
  74. 74 * @param type 类型
  75. 75 * @param docId 文档id
  76. 76 * @param updateParam 需要修改的字段和值
  77. 77 * @return
  78. 78 */
  79. 79 public static boolean updateDoc(String type, String docId, Map<String, String> updateParam) {
  80. 80 return ElasticSearchUtilsImp.updateDoc(type, docId, updateParam);
  81. 81 }
  82. 82
  83. 83 // --------------------以下是各种搜索方法--------------------------
  84. 84
  85. 85 /**
  86. 86 * 高亮搜索
  87. 87 *
  88. 88 * @param type 类型
  89. 89 * @param fieldName 段
  90. 90 * @param keyword 段值
  91. 91 * @return
  92. 92 */
  93. 93 public static Map<String, Object> searchDocHighlight(String type, String fieldName, String keyword) {
  94. 94 return ElasticSearchUtilsImp.searchDocHighlight(type, fieldName, keyword, 0, 10);
  95. 95 }
  96. 96
  97. 97 /**
  98. 98 * 高亮搜索
  99. 99 *
  100. 100 * @param type 类型
  101. 101 * @param fieldName 段
  102. 102 * @param keyword 关键词
  103. 103 * @param from 开始行数
  104. 104 * @param size 每页大小
  105. 105 * @return
  106. 106 */
  107. 107 public static Map<String, Object> searchDocHighlight(String type, String fieldName, String keyword, int from,
  108. 108 int size) {
  109. 109 return ElasticSearchUtilsImp.searchDocHighlight(type, fieldName, keyword, from, size);
  110. 110 }
  111. 111
  112. 112 /**
  113. 113 * or条件查询高亮
  114. 114 *
  115. 115 * @param type 类型
  116. 116 * @param shouldMap or条件和值
  117. 117 * @return
  118. 118 */
  119. 119 public static Map<String, Object> multiOrSearchDocHigh(String type, Map<String, String> shouldMap, int from,
  120. 120 int size) {
  121. 121 return ElasticSearchUtilsImp.multiOrSearchDocHigh(type, shouldMap, from, size);
  122. 122 }
  123. 123
  124. 124 /**
  125. 125 * 搜索
  126. 126 *
  127. 127 * @param type 类型
  128. 128 * @param fieldName 待搜索的字段
  129. 129 * @param keyword 待搜索的关键词
  130. 130 */
  131. 131 public static Map<String, Object> searchDoc(String type, String fieldName, String keyword) {
  132. 132 return ElasticSearchUtilsImp.searchDoc(type, fieldName, keyword, 0, 10);
  133. 133 }
  134. 134
  135. 135 /**
  136. 136 * 多个条件进行or查询
  137. 137 *
  138. 138 * @param type 类型
  139. 139 * @param shouldMap 进行or查询的段和值
  140. 140 * @return
  141. 141 */
  142. 142 public static Map<String, Object> multiOrSearchDoc(String type, Map<String, String> shouldMap) {
  143. 143 return ElasticSearchUtilsImp.multiOrSearchDoc(type, shouldMap, 0, 10);
  144. 144 }
  145. 145
  146. 146 /**
  147. 147 * 多个条件进行and查询
  148. 148 *
  149. 149 * @param type 类型
  150. 150 * @param mustMap 进行and查询的段和值
  151. 151 * @return
  152. 152 */
  153. 153 public static Map<String, Object> multiAndSearchDoc(String type, Map<String, String> mustMap) {
  154. 154 return ElasticSearchUtilsImp.multiAndSearchDoc(type, mustMap, 0, 10);
  155. 155 }
  156. 156 }

会使用到的其他助手类:StringUtils.java

StringUtils.java

具体的使用在我的另一个项目中有使用实例,该项目使用这个助手类实现了索引的各种操作,以及搜索展现功能。项目位置:https://github.com/yangtzeyufei/EasyBlog

ElasticSearch5在Ubuntu系统下的安装和Java调用的更多相关文章

  1. Ubuntu系统下环境安装遇到依赖冲突问题

    问题场景:在ubuntu系统下使用docker拉了一个python3.6的镜像,要在该容器中安装vim结果总是报已安装某些依赖的版本不满足要求 解决方法: 1.安装aptitude apt-get i ...

  2. 虚拟机Ubuntu系统下kaldi安装与编译简介

    kaldi官网:http://www.kaldi-asr.org/doc/index.html 在http://github.com/kaldi-asr/kaldi中直接下载kaldi的zip包,没有 ...

  3. Ubuntu 系统下如何安装pip3工具

    一.[导读]Ubuntu 系统内置了 Python2 和 Python3 两个版本的开发环境,却没有内置相应的 pip3 管理工具,本文将介绍如何在Ubuntu下如何快速安装 pip3 工具,并升级到 ...

  4. ubuntu系统下手动安装autoconf安装包

    首先简单介绍一下autoconf.Autoconf是一个可以适应多种unix类系统的shell脚本的工具. 我在往虚拟机中安装应用时,需要用到该工具,于是想下载一个.但是由于系统内核版本低,已不能用a ...

  5. Ubuntu 系统下 mongodb 安装和配置

    安装 MongoDB sudo apt-get install mongodb sudo apt-get install mongodb 关闭/启动 sudo service mongodb stop ...

  6. ubuntu系统下怎么安装gcc编译器

    你安装一个名字叫做build-essential的软件包,就可以一次将编译器.make工具.所有的编程头文件.函数库等东东全部安装上,其中也包括gcc编译器,这是非常稳妥的安装方式,安装命令是用roo ...

  7. Ubuntu系统下,pip3安装python3的pymysql包 报错的问题

    sudo pip3 --version 查看pip3的版本 sudo pip3 install --upgrade pip 更新pip3 sudo pip3 list  查看安装的包列表 如上图, p ...

  8. Python 基础之在ubuntu系统下安装双版本python

    前言:随着python升级更新,新版本较于老版本功能点也有不同地方,作为一个初学者应该了解旧版本的规则,也要继续学习新版本的知识.为了能更好去学习python,我在ubuntu安装python2和py ...

  9. Tex_安装_在Ubuntu系统下

    $\LaTeX$是一个强大的排版软件,在数学公式.表格.甚至是科学绘图方面有着独特优势.本文在Ubuntu系统下,整理Tex安装相关的操作,以为备忘.所引链接都未同作者商量,如有不妥望及时告知. 命令 ...

随机推荐

  1. 【树莓派】h2数据库操作相关

    之前在树莓派上面操作时候,遇到一些业务方面的bug,和团队中的同事经过多次尝试,但就是难以重现用户现场的问题. 但是问题却实实在在地发生,虽然并不是必然可重现的bug,但是也比较闹心: 发生了问题,也 ...

  2. python自动化框架(unnitest+selenium+htmlreport)

    上一篇零零散散的写了一些python unnitest的一些知识,这里讲讲我在实际中使用到的自动化测试框架,算是上篇记录的补充!其实我觉得:什么框架都无所谓,关键是当如果用你的框架发现了bug,能尽量 ...

  3. 检测Windows程序的内存和资源泄漏之原生语言环境

    最近接连收到大客户的反馈,我们开发的一个软件,姑且称之为App-E吧,在项目规模特别大的情况下,长时间使用会逐渐耗尽内存,运行越来越缓慢,软件最终崩溃.由于App-E是使用混合语言开发的,主界面使用C ...

  4. iOS开发之判断横竖屏切换

    /** *  当屏幕即将旋转的时候调用 * *  @param toInterfaceOrientation 旋转完毕后的最终方向 *  @param duration  旋转动画所花费的时间 */ ...

  5. Spring定时任务解决博客缓存数据更新问题

    最近在做博客系统的时候,由于很多页面都有右边侧边栏,内容包括博客分类信息,归档日志,热门文章,标签列表等,为了不想每次访问页面都去查询数据库,因为本身这些东西相对来说是比较固定的,但是也有可能在网站后 ...

  6. git pull错误记录及解决

    执行操作:$ git pull 返回错误: error: RPC failed; result=7, HTTP code = 0 fatal: The remote and hung up unexp ...

  7. Spring MVC 处理异常的3种方式

    使用Spring MVC开发的博客网站时,遇到了如何处理业务层抛出的异常的问题,查阅到了spring官方博客-spring MVC中异常的处理,以下将会以登录模块为示例. 愚蠢的处理方式 处理异常遵循 ...

  8. python+request+robot framework接口自动化测试

    python+requests实现接口的请求前篇已经介绍,还有不懂或者疑问的可以访问 python+request接口自动化框架 目前我们需要考虑的是如何实现关键字驱动实现接口自动化输出,通过关键字的 ...

  9. Zabbix3.0部署最佳实践

    Zabbix3整个web界面做了一个全新的设计. 更多新特性请点击当前字幕查看   笔者QQ:572891887 Linux架构交流群:471443208 1.1Zabbix环境准备 [root@li ...

  10. jquery练习之瀑布流

    最近有空简单学习了下瀑布流,写完后想和大家一起分享下,但我知道我的代码有很多缺陷不足,希望多多包涵.(纯属兴趣非专业学习人士) 众所周知,瀑布流大概分为2种,一种是浮动式的瀑布流,一种是定位式的瀑布流 ...