1.  概述

Java REST Client 有两种风格:

  • Java Low Level REST Client :用于Elasticsearch的官方低级客户端。它允许通过http与Elasticsearch集群通信。将请求编排和响应反编排留给用户自己处理。它兼容所有的Elasticsearch版本。(PS:学过WebService的话,对编排与反编排这个概念应该不陌生。可以理解为对请求参数的封装,以及对响应结果的解析)
  • Java High Level REST Client :用于Elasticsearch的官方高级客户端。它是基于低级客户端的,它提供很多API,并负责请求的编排与响应的反编排。(PS:就好比是,一个是传自己拼接好的字符串,并且自己解析返回的结果;而另一个是传对象,返回的结果也已经封装好了,直接是对象,更加规范了参数的名称以及格式,更加面对对象一点)

(PS:所谓低级与高级,我觉得一个很形象的比喻是,面向过程编程与面向对象编程)

在 Elasticsearch 7.0 中不建议使用TransportClient,并且在8.0中会完全删除TransportClient。因此,官方更建议我们用Java High Level REST Client,它执行HTTP请求,而不是序列号的Java请求。既然如此,这里就直接用高级了。

2.  Java High Level REST Client (高级REST客户端)

2.1.  Maven仓库

  1. <dependency>
  2. <groupId>org.elasticsearch.client</groupId>
  3. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  4. <version>6.5.4</version>
  5. </dependency>

2.2.  依赖

  • org.elasticsearch.client:elasticsearch-rest-client
  • org.elasticsearch:elasticsearch

2.3.  初始化

  1. RestHighLevelClient client = new RestHighLevelClient(
  2. RestClient.builder(
  3. new HttpHost("localhost", 9200, "http"),
  4. new HttpHost("localhost", 9201, "http")));

高级客户端内部会创建低级客户端用于基于提供的builder执行请求。低级客户端维护一个连接池,并启动一些线程,因此当你用完以后应该关闭高级客户端,并且在内部它将会关闭低级客户端,以释放这些资源。关闭客户端可以使用close()方法:

  1. client.close();

2.4.  文档API

2.4.1.  添加文档

IndexRequest

  1. IndexRequest request = new IndexRequest("posts", "doc", "1");
  2. String jsonString = "{\"user\":\"kimchy\",\"postDate\":\"2013-01-30\",\"message\":\"trying out Elasticsearch\"}";
  3. request.source(jsonString, XContentType.JSON);

提供文档source的方式还有很多,比如:

通过Map的方式提供文档source

通过XContentBuilder方式提供source

通过Object的方式(键值对)提供source

可选参数

同步执行

异步执行

你也可以异步执行 IndexRequest,为此你需要指定一个监听器来处理这个异步响应结果:

一个典型的监听器看起来是这样的:

IndexResponse

如果有版本冲突,将会抛出ElasticsearchException

同样的异常也有可能发生在当opType设置为create的时候,且相同索引、相同类型、相同ID的文档已经存在时。例如:

2.4.2.  查看文档

Get Request

可选参数

同步执行

异步执行

Get Response

当索引不存在,或者指定的文档的版本不存在时,响应状态吗是404,并且抛出ElasticsearchException

2.4.3.  文档是否存在

2.4.4.  删除文档

Delete Request

可选参数

同添加

2.5.  搜索API

Search Request

基本格式是这样的:

大多数查询参数被添加到 SearchSourceBuilder

可选参数

SearchSourceBuilder

控制检索行为的大部分选项都可以在SearchSourceBuilder中设置。下面是一个常见选项的例子:

在这个例子中,我们首先创建了一个SearchSourceBuilder对象,并且带着默认选项。然后设置了一个term查询,接着设置检索的位置和数量,最后设置超时时间

在设置完这些选项以后,我们只需要把SearchSourceBuilder加入到SearchRequest中即可

构建Query

用QueryBuilder来创建Serarch Query。QueryBuilder支持Elasticsearch DSL中每一种Query

例如:

还可以通过QueryBuilders工具类来创建QueryBuilder对象,例如:

无论是用哪种方式创建,最后一定要把QueryBuilder添加到SearchSourceBuilder中

排序

SearchSourceBuilder 可以添加一个或多个 SortBuilder

SortBuilder有四种实现:FieldSortBuilder、GeoDistanceSortBuilder、ScoreSortBuilder、ScriptSortBuilder

聚集函数

同步执行

异步执行

从查询响应中取出文档

3.  示例

3.1.  准备数据

3.1.1.  安装IK分词器插件

  1. ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.5.4/elasticsearch-analysis-ik-6.5.4.zip

3.1.2.  创建索引

  1. curl -X PUT "localhost:9200/book" -H 'Content-Type: application/json' -d'
  2. {
  3. "mappings":{
  4. "_doc":{
  5. "properties":{
  6. "id":{
  7. "type":"integer"
  8. },
  9. "name":{
  10. "type":"text",
  11. "analyzer":"ik_max_word",
  12. "search_analyzer":"ik_max_word"
  13. },
  14. "author":{
  15. "type":"text",
  16. "analyzer":"ik_max_word",
  17. "search_analyzer":"ik_max_word"
  18. },
  19. "category":{
  20. "type":"integer"
  21. },
  22. "price":{
  23. "type":"double"
  24. },
  25. "status":{
  26. "type":"short"
  27. },
  28. "sellReason":{
  29. "type":"text",
  30. "analyzer":"ik_max_word",
  31. "search_analyzer":"ik_max_word"
  32. },
  33. "sellTime":{
  34. "type":"date",
  35. "format":"yyyy-MM-dd"
  36. }
  37. }
  38. }
  39. }
  40. }
  41. '

3.1.3.  数据预览

3.2.  示例代码

3.2.1.  完整的pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.1.1.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.cjs.example</groupId>
  12. <artifactId>elasticsearch-demo</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>elasticsearch-demo</name>
  15. <description></description>
  16.  
  17. <properties>
  18. <java.version>1.8</java.version>
  19. </properties>
  20.  
  21. <dependencies>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-web</artifactId>
  25. </dependency>
  26. <dependency>
  27. <groupId>org.springframework.boot</groupId>
  28. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  29. </dependency>
  30.  
  31. <dependency>
  32. <groupId>org.elasticsearch.client</groupId>
  33. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  34. <version>6.5.4</version>
  35. </dependency>
  36.  
  37. <dependency>
  38. <groupId>org.apache.commons</groupId>
  39. <artifactId>commons-lang3</artifactId>
  40. <version>3.8</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>com.alibaba</groupId>
  44. <artifactId>fastjson</artifactId>
  45. <version>1.2.54</version>
  46. </dependency>
  47. <dependency>
  48. <groupId>ch.qos.logback</groupId>
  49. <artifactId>logback-core</artifactId>
  50. <version>1.2.3</version>
  51. </dependency>
  52. <dependency>
  53. <groupId>org.projectlombok</groupId>
  54. <artifactId>lombok</artifactId>
  55. <optional>true</optional>
  56. </dependency>
  57. <dependency>
  58. <groupId>org.springframework.boot</groupId>
  59. <artifactId>spring-boot-starter-test</artifactId>
  60. <scope>test</scope>
  61. </dependency>
  62. </dependencies>
  63.  
  64. <build>
  65. <plugins>
  66. <plugin>
  67. <groupId>org.springframework.boot</groupId>
  68. <artifactId>spring-boot-maven-plugin</artifactId>
  69. </plugin>
  70. </plugins>
  71. </build>
  72.  
  73. </project>

3.2.2.  配置

  1. package com.cjs.example.elasticsearch.config;
  2.  
  3. import org.apache.http.HttpHost;
  4. import org.elasticsearch.client.RestClient;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8.  
  9. /**
  10. * @author ChengJianSheng
  11. * @date 2019-01-07
  12. */
  13. @Configuration
  14. public class ElasticsearchClientConfig {
  15.  
  16. @Bean
  17. public RestHighLevelClient restHighLevelClient() {
  18. RestHighLevelClient client = new RestHighLevelClient(
  19. RestClient.builder(
  20. new HttpHost("localhost", 9200, "http")));
  21. return client;
  22. }
  23.  
  24. }

3.2.3.  domain

  1. package com.cjs.example.elasticsearch.domain.model;
  2.  
  3. import lombok.Data;
  4.  
  5. import java.io.Serializable;
  6.  
  7. /**
  8. * 图书
  9. * @author ChengJianSheng
  10. * @date 2019-01-07
  11. */
  12. @Data
  13. public class BookModel implements Serializable {
  14.  
  15. private Integer id; // 图书ID
  16.  
  17. private String name; // 图书名称
  18.  
  19. private String author; // 作者
  20.  
  21. private Integer category; // 图书分类
  22.  
  23. private Double price; // 图书价格
  24.  
  25. private String sellReason; // 上架理由
  26.  
  27. private String sellTime; // 上架时间
  28.  
  29. private Integer status; // 状态(1:可售,0:不可售)
  30.  
  31. }

3.2.4.  Controller

  1. package com.cjs.example.elasticsearch.controller;
  2.  
  3. import com.alibaba.fastjson.JSON;
  4. import com.cjs.example.elasticsearch.domain.common.BaseResult;
  5. import com.cjs.example.elasticsearch.domain.common.Page;
  6. import com.cjs.example.elasticsearch.domain.model.BookModel;
  7. import com.cjs.example.elasticsearch.domain.vo.BookRequestVO;
  8. import com.cjs.example.elasticsearch.service.BookService;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.springframework.beans.factory.annotation.Autowired;
  11. import org.springframework.web.bind.annotation.*;
  12.  
  13. /**
  14. * 文档操作
  15. * @author ChengJianSheng
  16. * @date 2019-01-07
  17. */
  18. @Slf4j
  19. @RestController
  20. @RequestMapping("/book")
  21. public class BookController {
  22.  
  23. @Autowired
  24. private BookService bookService;
  25.  
  26. /**
  27. * 列表分页查询
  28. */
  29. @GetMapping("/list")
  30. public BaseResult list(BookRequestVO bookRequestVO) {
  31. Page<BookModel> page = bookService.list(bookRequestVO);
  32. if (null == page) {
  33. return BaseResult.error();
  34. }
  35. return BaseResult.ok(page);
  36. }
  37.  
  38. /**
  39. * 查看文档
  40. */
  41. @GetMapping("/detail")
  42. public BaseResult detail(Integer id) {
  43. if (null == id) {
  44. return BaseResult.error("ID不能为空");
  45. }
  46. BookModel book = bookService.detail(id);
  47. return BaseResult.ok(book);
  48. }
  49.  
  50. /**
  51. * 添加文档
  52. */
  53. @PostMapping("/add")
  54. public BaseResult add(@RequestBody BookModel bookModel) {
  55. bookService.save(bookModel);
  56. log.info("插入文档成功!请求参数: {}", JSON.toJSONString(bookModel));
  57. return BaseResult.ok();
  58. }
  59.  
  60. /**
  61. * 修改文档
  62. */
  63. @PostMapping("/update")
  64. public BaseResult update(@RequestBody BookModel bookModel) {
  65. Integer id = bookModel.getId();
  66. if (null == id) {
  67. return BaseResult.error("ID不能为空");
  68. }
  69. BookModel book = bookService.detail(id);
  70. if (null == book) {
  71. return BaseResult.error("记录不存在");
  72. }
  73. bookService.update(bookModel);
  74. log.info("更新文档成功!请求参数: {}", JSON.toJSONString(bookModel));
  75. return BaseResult.ok();
  76. }
  77.  
  78. /**
  79. * 删除文档
  80. */
  81. @GetMapping("/delete")
  82. public BaseResult delete(Integer id) {
  83. if (null == id) {
  84. return BaseResult.error("ID不能为空");
  85. }
  86. bookService.delete(id);
  87. return BaseResult.ok();
  88. }
  89.  
  90. }

3.2.5.  Service

  1. package com.cjs.example.elasticsearch.service.impl;
  2.  
  3. import com.alibaba.fastjson.JSON;
  4. import com.cjs.example.elasticsearch.domain.common.Page;
  5. import com.cjs.example.elasticsearch.domain.model.BookModel;
  6. import com.cjs.example.elasticsearch.domain.vo.BookRequestVO;
  7. import com.cjs.example.elasticsearch.service.BookService;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.apache.commons.lang3.StringUtils;
  10. import org.elasticsearch.action.ActionListener;
  11. import org.elasticsearch.action.DocWriteResponse;
  12. import org.elasticsearch.action.delete.DeleteRequest;
  13. import org.elasticsearch.action.delete.DeleteResponse;
  14. import org.elasticsearch.action.get.GetRequest;
  15. import org.elasticsearch.action.get.GetResponse;
  16. import org.elasticsearch.action.index.IndexRequest;
  17. import org.elasticsearch.action.index.IndexResponse;
  18. import org.elasticsearch.action.search.SearchRequest;
  19. import org.elasticsearch.action.search.SearchResponse;
  20. import org.elasticsearch.action.support.replication.ReplicationResponse;
  21. import org.elasticsearch.action.update.UpdateRequest;
  22. import org.elasticsearch.action.update.UpdateResponse;
  23. import org.elasticsearch.client.RequestOptions;
  24. import org.elasticsearch.client.RestHighLevelClient;
  25. import org.elasticsearch.common.unit.TimeValue;
  26. import org.elasticsearch.index.query.BoolQueryBuilder;
  27. import org.elasticsearch.index.query.QueryBuilders;
  28. import org.elasticsearch.rest.RestStatus;
  29. import org.elasticsearch.search.SearchHit;
  30. import org.elasticsearch.search.SearchHits;
  31. import org.elasticsearch.search.builder.SearchSourceBuilder;
  32. import org.elasticsearch.search.sort.FieldSortBuilder;
  33. import org.elasticsearch.search.sort.SortOrder;
  34. import org.springframework.beans.factory.annotation.Autowired;
  35. import org.springframework.stereotype.Service;
  36. import org.springframework.util.CollectionUtils;
  37.  
  38. import java.io.IOException;
  39. import java.util.*;
  40. import java.util.stream.Collectors;
  41.  
  42. /**
  43. * @author ChengJianSheng
  44. * @date 2019-01-07
  45. */
  46. @Slf4j
  47. @Service
  48. public class BookServiceImpl implements BookService {
  49.  
  50. private static final String INDEX_NAME = "book";
  51. private static final String INDEX_TYPE = "_doc";
  52.  
  53. @Autowired
  54. private RestHighLevelClient client;
  55.  
  56. @Override
  57. public Page<BookModel> list(BookRequestVO bookRequestVO) {
  58. int pageNo = bookRequestVO.getPageNo();
  59. int pageSize = bookRequestVO.getPageSize();
  60.  
  61. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  62. sourceBuilder.from(pageNo - 1);
  63. sourceBuilder.size(pageSize);
  64. sourceBuilder.sort(new FieldSortBuilder("id").order(SortOrder.ASC));
  65. // sourceBuilder.query(QueryBuilders.matchAllQuery());
  66.  
  67. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  68.  
  69. if (StringUtils.isNotBlank(bookRequestVO.getName())) {
  70. boolQueryBuilder.must(QueryBuilders.matchQuery("name", bookRequestVO.getName()));
  71. }
  72. if (StringUtils.isNotBlank(bookRequestVO.getAuthor())) {
  73. boolQueryBuilder.must(QueryBuilders.matchQuery("author", bookRequestVO.getAuthor()));
  74. }
  75. if (null != bookRequestVO.getStatus()) {
  76. boolQueryBuilder.must(QueryBuilders.termQuery("status", bookRequestVO.getStatus()));
  77. }
  78. if (StringUtils.isNotBlank(bookRequestVO.getSellTime())) {
  79. boolQueryBuilder.must(QueryBuilders.termQuery("sellTime", bookRequestVO.getSellTime()));
  80. }
  81. if (StringUtils.isNotBlank(bookRequestVO.getCategories())) {
  82. String[] categoryArr = bookRequestVO.getCategories().split(",");
  83. List<Integer> categoryList = Arrays.asList(categoryArr).stream().map(e->Integer.valueOf(e)).collect(Collectors.toList());
  84. BoolQueryBuilder categoryBoolQueryBuilder = QueryBuilders.boolQuery();
  85. for (Integer category : categoryList) {
  86. categoryBoolQueryBuilder.should(QueryBuilders.termQuery("category", category));
  87. }
  88. boolQueryBuilder.must(categoryBoolQueryBuilder);
  89. }
  90.  
  91. sourceBuilder.query(boolQueryBuilder);
  92.  
  93. SearchRequest searchRequest = new SearchRequest();
  94. searchRequest.indices(INDEX_NAME);
  95. searchRequest.source(sourceBuilder);
  96.  
  97. try {
  98. SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
  99.  
  100. RestStatus restStatus = searchResponse.status();
  101. if (restStatus != RestStatus.OK) {
  102. return null;
  103. }
  104.  
  105. List<BookModel> list = new ArrayList<>();
  106. SearchHits searchHits = searchResponse.getHits();
  107. for (SearchHit hit : searchHits.getHits()) {
  108. String source = hit.getSourceAsString();
  109. BookModel book = JSON.parseObject(source, BookModel.class);
  110. list.add(book);
  111. }
  112.  
  113. long totalHits = searchHits.getTotalHits();
  114.  
  115. Page<BookModel> page = new Page<>(pageNo, pageSize, totalHits, list);
  116.  
  117. TimeValue took = searchResponse.getTook();
  118. log.info("查询成功!请求参数: {}, 用时{}毫秒", searchRequest.source().toString(), took.millis());
  119.  
  120. return page;
  121. } catch (IOException e) {
  122. log.error("查询失败!原因: {}", e.getMessage(), e);
  123. }
  124.  
  125. return null;
  126. }
  127.  
  128. @Override
  129. public void save(BookModel bookModel) {
  130. Map<String, Object> jsonMap = new HashMap<>();
  131. jsonMap.put("id", bookModel.getId());
  132. jsonMap.put("name", bookModel.getName());
  133. jsonMap.put("author", bookModel.getAuthor());
  134. jsonMap.put("category", bookModel.getCategory());
  135. jsonMap.put("price", bookModel.getPrice());
  136. jsonMap.put("sellTime", bookModel.getSellTime());
  137. jsonMap.put("sellReason", bookModel.getSellReason());
  138. jsonMap.put("status", bookModel.getStatus());
  139.  
  140. IndexRequest indexRequest = new IndexRequest(INDEX_NAME, INDEX_TYPE, String.valueOf(bookModel.getId()));
  141. indexRequest.source(jsonMap);
  142.  
  143. client.indexAsync(indexRequest, RequestOptions.DEFAULT, new ActionListener<IndexResponse>() {
  144. @Override
  145. public void onResponse(IndexResponse indexResponse) {
  146. String index = indexResponse.getIndex();
  147. String type = indexResponse.getType();
  148. String id = indexResponse.getId();
  149. long version = indexResponse.getVersion();
  150.  
  151. log.info("Index: {}, Type: {}, Id: {}, Version: {}", index, type, id, version);
  152.  
  153. if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
  154. log.info("写入文档");
  155. } else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
  156. log.info("修改文档");
  157. }
  158. ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();
  159. if (shardInfo.getTotal() != shardInfo.getSuccessful()) {
  160. log.warn("部分分片写入成功");
  161. }
  162. if (shardInfo.getFailed() > 0) {
  163. for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {
  164. String reason = failure.reason();
  165. log.warn("失败原因: {}", reason);
  166. }
  167. }
  168. }
  169.  
  170. @Override
  171. public void onFailure(Exception e) {
  172. log.error(e.getMessage(), e);
  173. }
  174. });
  175. }
  176.  
  177. @Override
  178. public void update(BookModel bookModel) {
  179. Map<String, Object> jsonMap = new HashMap<>();
  180. jsonMap.put("sellReason", bookModel.getSellReason());
  181. UpdateRequest request = new UpdateRequest(INDEX_NAME, INDEX_TYPE, String.valueOf(bookModel.getId()));
  182. request.doc(jsonMap);
  183. try {
  184. UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
  185. } catch (IOException e) {
  186. log.error("更新失败!原因: {}", e.getMessage(), e);
  187. }
  188. }
  189.  
  190. @Override
  191. public void delete(int id) {
  192. DeleteRequest request = new DeleteRequest(INDEX_NAME, INDEX_TYPE, String.valueOf(id));
  193. try {
  194. DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
  195. if (deleteResponse.status() == RestStatus.OK) {
  196. log.info("删除成功!id: {}", id);
  197. }
  198. } catch (IOException e) {
  199. log.error("删除失败!原因: {}", e.getMessage(), e);
  200. }
  201. }
  202.  
  203. @Override
  204. public BookModel detail(int id) {
  205. GetRequest getRequest = new GetRequest(INDEX_NAME, INDEX_TYPE, String.valueOf(id));
  206. try {
  207. GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
  208. if (getResponse.isExists()) {
  209. String source = getResponse.getSourceAsString();
  210. BookModel book = JSON.parseObject(source, BookModel.class);
  211. return book;
  212. }
  213. } catch (IOException e) {
  214. log.error("查看失败!原因: {}", e.getMessage(), e);
  215. }
  216. return null;
  217. }
  218. }

3.2.6.  页面

  1. <!DOCTYPE html>
  2. <html lang="zh">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>图书列表</title>
  6.  
  7. <link rel="stylesheet" href="/bootstrap-4/css/bootstrap.min.css">
  8. <link rel="stylesheet" href="/bootstrap-table/bootstrap-table.css">
  9.  
  10. <script src="jquery-3.3.1.min.js"></script>
  11. <script src="/bootstrap-4/js/bootstrap.min.js"></script>
  12. <script src="/bootstrap-table/bootstrap-table.js"></script>
  13. <script src="/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script>
  14. <script>
  15. $(function(){
  16.  
  17. $('#table').bootstrapTable({
  18. url: '/book/list',
  19. method: 'get',
  20. sidePagination: 'server',
  21. responseHandler: function(res) { // 加载服务器数据之前的处理程序,可以用来格式化数据。参数:res为从服务器请求到的数据。
  22. var result = {};
  23. result.total = res.data.totalCount;
  24. result.rows = res.data.pageList;
  25. return result;
  26. },
  27. pagination: true,
  28. pageSize: 3, // 初始PageSize
  29. queryParams: function(params) {
  30. var req = {
  31. pageSize: params.limit,
  32. pageNo: params.offset + 1
  33. };
  34. return req;
  35. },
  36. striped: true,
  37. search: true,
  38. columns: [{
  39. field: 'id',
  40. title: 'ID'
  41. }, {
  42. field: 'name',
  43. title: '名称'
  44. }, {
  45. field: 'author',
  46. title: '作者'
  47. }, {
  48. field: 'price',
  49. title: '单价'
  50. }, {
  51. field: 'sellTime',
  52. title: '上架时间'
  53. }, {
  54. field: 'status',
  55. title: '状态',
  56. formatter: function(value) {
  57. if (value == 1) {
  58. return '<span style="color: green">可售</span>';
  59. } else {
  60. return '<span style="color: red">不可售</span>';
  61. }
  62. }
  63. }, {
  64. field: 'category',
  65. title: '分类',
  66. formatter: function(value) {
  67. if (value == 10010) {
  68. return '中国当代小说';
  69. } else if (value == 10011) {
  70. return '武侠小说';
  71. } else if (value == 10012) {
  72. return '爱情小说';
  73. } else if (value == 10013) {
  74. return '中国当代随笔';
  75. }
  76. }
  77. }, {
  78. field: 'sellReason',
  79. title: '上架理由'
  80. }, {
  81. title: '操作',
  82. formatter: function() {
  83. return '<a href="#">修改</a> <a href="#">删除</a>';
  84. }
  85. }
  86. ]
  87. });
  88.  
  89. });
  90. </script>
  91. </head>
  92. <body>
  93. <div class="table-responsive" style="padding: 10px 30px">
  94. <table id="table" class="table text-nowrap"></table>
  95. </div>
  96. </body>
  97. </html>

3.3.  演示

重点演示几个查询

返回结果:

  1. {
  2. "code": 200,
  3. "success": true,
  4. "msg": "SUCCESS",
  5. "data": {
  6. "pageNumber": 1,
  7. "pageSize": 10,
  8. "totalCount": 2,
  9. "pageList": [
  10. {
  11. "id": 2,
  12. "name": "倚天屠龙记(全四册)",
  13. "author": "金庸",
  14. "category": 10011,
  15. "price": 70.4,
  16. "sellReason": "武林至尊,宝刀屠龙,号令天下,莫敢不从。",
  17. "sellTime": "2018-11-11",
  18. "status": 1
  19. },
  20. {
  21. "id": 3,
  22. "name": "神雕侠侣",
  23. "author": "金庸",
  24. "category": 10011,
  25. "price": 70,
  26. "sellReason": "风陵渡口初相遇,一见杨过误终身",
  27. "sellTime": "2018-11-11",
  28. "status": 1
  29. }
  30. ]
  31. }
  32. }

上面的查询对应的Elasticsearch DSL是这样的:

  1. {
  2. "from":0,
  3. "size":10,
  4. "query":{
  5. "bool":{
  6. "must":[
  7. {
  8. "match":{
  9. "author":{
  10. "query":"金庸",
  11. "operator":"OR",
  12. "prefix_length":0,
  13. "max_expansions":50,
  14. "fuzzy_transpositions":true,
  15. "lenient":false,
  16. "zero_terms_query":"NONE",
  17. "auto_generate_synonyms_phrase_query":true,
  18. "boost":1
  19. }
  20. }
  21. },
  22. {
  23. "term":{
  24. "status":{
  25. "value":1,
  26. "boost":1
  27. }
  28. }
  29. },
  30. {
  31. "bool":{
  32. "should":[
  33. {
  34. "term":{
  35. "category":{
  36. "value":10010,
  37. "boost":1
  38. }
  39. }
  40. },
  41. {
  42. "term":{
  43. "category":{
  44. "value":10011,
  45. "boost":1
  46. }
  47. }
  48. },
  49. {
  50. "term":{
  51. "category":{
  52. "value":10012,
  53. "boost":1
  54. }
  55. }
  56. }
  57. ],
  58. "adjust_pure_negative":true,
  59. "boost":1
  60. }
  61. }
  62. ],
  63. "adjust_pure_negative":true,
  64. "boost":1
  65. }
  66. },
  67. "sort":[
  68. {
  69. "id":{
  70. "order":"asc"
  71. }
  72. }
  73. ]
  74. }

3.4.  工程结构

4.  参考

https://github.com/medcl/elasticsearch-analysis-ik

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-search.html

https://bootstrap-table.wenzhixin.net.cn/documentation/

5.  其它相关

Elasticsearch 分词器

Elasticsearch Document

Elasticsearch Search API

Elasticsearch查询

Elasticsearch Mapping

SpringBoot+Elasticsearch

ELK快速搭建日志平台

Elasticsearch Java高级客户端的更多相关文章

  1. NEST - Elasticsearch 的高级客户端

    NEST - High level client Version:5.x 英文原文地址:NEST - High level client 个人建议:学习 NEST 的官方文档时,按照顺序进行,不宜跳来 ...

  2. elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    一.ES Client 简介 1. ES是一个服务,采用C/S结构 2. 回顾 ES的架构 3. ES支持的客户端连接方式 3.1 REST API ,端口 9200 这种连接方式对应于架构图中的RE ...

  3. Elasticsearch Java client(ES Client 简介、Java REST Client、Java Client、Spring Data Elasticsearch)

    elasticsearch系列七:ES Java客户端-Elasticsearch Java client(ES Client 简介.Java REST Client.Java Client.Spri ...

  4. Elasticsearch java api操作(二)(Java High Level Rest Client)

    一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...

  5. Elasticsearch java api操作(一)(Java Low Level Rest Client)

    一.说明: 一.Elasticsearch提供了两个JAVA REST Client版本: 1.java low level rest client: 低级别的rest客户端,通过http与集群交互, ...

  6. [Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    如若转载请注明出处: http://www.cnblogs.com/wang-meng/p/5898837.html   谢谢.上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大 ...

  7. [搜索]ElasticSearch Java Api(一) -添加数据创建索引

    转载:http://blog.csdn.net/napoay/article/details/51707023 ElasticSearch JAVA API官网文档:https://www.elast ...

  8. Elasticsearch java api 基本搜索部分详解

    文档是结合几个博客整理出来的,内容大部分为转载内容.在使用过程中,对一些疑问点进行了整理与解析. Elasticsearch java api 基本搜索部分详解 ElasticSearch 常用的查询 ...

  9. 转载:[Java面经]干货整理, Java面试题(覆盖Java基础,Java高级,JavaEE,数据库,设计模式等)

    原文:http://www.cnblogs.com/wang-meng/p/5898837.html 一:继承.抽象类与接口区别.访问控制(private, public, protected,默认) ...

随机推荐

  1. compact_op.go

    package clientv3 import (     pb "github.com/coreos/etcd/etcdserver/etcdserverpb" ) // Com ...

  2. proxy.go

    )     for {         select {         case <-otherSwitch:             complete <- true          ...

  3. BZOJ_4590_[Shoi2015]自动刷题机_二分答案

    BZOJ_4590_[Shoi2015]自动刷题机_二分答案 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题 ...

  4. BZOJ_2238_Mst_树剖+线段树

    BZOJ_2238_Mst_树剖+线段树 Description 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影 ...

  5. awk的递归

    想来惭愧,之前写的一篇文章<用awk写递归>里多少是传递里错误的信息.虽然那篇文章目的上是为了给出一种思路,但实际上awk是可以支持函数局部变量的. awk对于局部变量的支持比起大多数过程 ...

  6. java 基础知识小结

    1. java 有三个求整的函数 math.floor ()  (floor 是地板的意思)  向下求整 math.ceil ()  (ceil 是天花板的意思 ) 向上求整 math.round() ...

  7. Django模板修炼

    引言:由于我们在使用Django框架时,不会将HTML代码采用硬编码的方式,因为会有以下缺点: 1:对页面设计进行的任何改变都必须对 Python 代码进行相应的修改. 站点设计的修改往往比底层 Py ...

  8. LeetCode算法题-Unique Morse Code Words(Java实现)

    这是悦乐书的第318次更新,第339篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第186题(顺位题号是804).国际莫尔斯电码定义了一种标准编码,其中每个字母映射到一系 ...

  9. 树莓派3b+_32位linux系统arm架构安装JDK

    如图我的Raspbian系统如下图版本信息: 可以看到是armv7l,我查了一下是32位的arm架构,即下载第一个就好了 然后用SSH Secure Shell远程上去把压缩包或者解压后的文件传过去 ...

  10. Gradle中的闭包

    Gradle是基于Groovy的DSL基础上的构建工具,Gradle中的闭包,其原型上实际上即Groovy中闭包.而在表现形式上,其实,Gradle更多的是以约定和基于约定基础上的配置去展现.但本质上 ...