当前位置:   article > 正文

全文检索Elasticearch_elasticearch release date

elasticearch release date

1 ElasticSearch介绍

1.1、介绍

Elasticsearch 是一个非常强大的搜索引擎。它目前被广泛地使用于各个 IT 公司。Elasticsearch 是由 Elastic 公司创建。它的代码位于 GitHub - elastic/elasticsearch: Free and Open, Distributed, RESTful Search Engine。Elasticsearch 是一个分布式、免费和开放的搜索和分析引擎,适用于所有类型的数据,包括文本、数字、地理空间、结构化和非结构化数据。 Elasticsearch 基于 Apache Lucene 构建,并于 2010 年由 Elasticsearch N.V. 首次发布(现在称为 Elastic)。Elasticsearch 以其简单的 REST API、分布式特性、速度和可扩展性而闻名,是 Elastic Stack 的核心组件,Elastic Stack 是一组用于数据摄取、丰富、存储、分析和可视化的免费开放工具。 通常被称为 ELK Stack。Elastic 公司也同时拥有 Logstash 及 Kibana 开源项目。这个三个项目组合在一起,就形成了 ELK 软件栈。他们三个共同形成了一个强大的生态圈。简单地说,Logstash 负责数据的采集,处理(丰富数据,数据转换等),Kibana 负责数据展示,分析,管理,监督,警报及方案。Elasticsearch 处于最核心的位置,它可以帮我们对数据进行存储,并快速地搜索及分析数据

官方网址:https://www.elastic.co/cn/products/elasticsearch

Github:https://github.com/elastic/elasticsearch

总结:

1、elasticsearch是一个基于Lucene的高扩展的分布式搜索服务器,支持开箱即用。

2、elasticsearch隐藏了Lucene的复杂性,对外提供Restful 接口来操作索引、搜索。

突出优点:

1.扩展性好,可部署上百台服务器集群,处理PB级数据。

2.近实时的去索引数据、搜索数据。

2 原理与应用

2.1索引结构

下图是ElasticSearch的索引结构,下边黑色部分是物理结构,上边黄色部分是逻辑结构,逻辑结构也是为了更好的去描述ElasticSearch的工作原理及去使用物理结构中的索引文件。

逻辑结构部分是一个倒排索引表:

1、将要搜索的文档内容分词,所有不重复的词组成分词列表。

2、将搜索的文档最终以Document方式存储起来。

3、每个词和docment都有关联。

如下:

现在,如果我们想搜索quick brown ,我们只需要查找包含每个词条的文档:

两个文档都匹配,但是第一个文档比第二个匹配度更高。如果我们使用仅计算匹配词条数量的简单相似性算法,那么,我们可以说,对于我们查询的相关性来讲,第一个文档比第二个文档更佳。

3 ES对外接口(开发人员关注)

1)JAVA API接口

http://www.ibm.com/developerworks/library/j-use-elasticsearch-java-apps/index.html

2)RESTful API接口

常见的增、删、改、查操作实现:

http://blog.csdn.net/laoyang360/article/details/51931981

4 ES遇到问题怎么办?

1)国外:https://discuss.elastic.co/

  1. 国内:http://elasticsearch.cn/

5 映射

5.1 映射维护方法

1、查询所有索引的映射:

GET:http://localhost:9200/_mapping

2、创建映射

post 请求:http://localhost:9200/xc_course/doc/_mapping

一个例子:

  1. {
  2. "properties": {
  3. "name": {
  4. "type": "text"
  5. },
  6. "description": {
  7. "type": "text"
  8. },
  9. "studymodel": {
  10. "type": "keyword"
  11. }
  12. }
  13. }

3、更新映射

映射创建成功可以添加新字段,已有字段不允许更新。

4、删除映射

通过删除索引来删除映射。

5.2 常用映射类型
5.2.1 text文本字段

下图是ES6.2核心的字段类型如下:

字符串包括text和keyword两种类型:

1、text

1)analyzer

通过analyzer属性指定分词器。

下边指定name的字段类型为text,使用ik分词器的ik_max_word分词模式。

  1. "name": {
  2. "type": "text",
  3. "analyzer": "ik_max_word"
  4. }

上边指定了analyzer是指在索引和搜索都使用ik_max_word,如果单独想定义搜索时使用的分词器则可以通过search_analyzer属性。

对于ik分词器建议是索引时使用ik_max_word将搜索内容进行细粒度分词,搜索时使用ik_smart提高搜索精确性。

  1. "name": {
  2. "type": "text",
  3. "analyzer": "ik_max_word",
  4. "search_analyzer": "ik_smart"
  5. }

2)index

通过index属性指定是否索引。

默认为index=true,即要进行索引,只有进行索引才可以从索引库搜索到。

但是也有一些内容不需要索引,比如:商品图片地址只被用来展示图片,不进行搜索图片,此时可以将index设置为false。

删除索引,重新创建映射,将pic的index设置为false,尝试根据pic去搜索,结果搜索不到数据

  1. "pic": {
  2. "type": "text",
  3. "index":false
  4. }
5.2.2 keyword关键字字段

上边介绍的text文本字段在映射时要设置分词器,keyword字段为关键字字段,通常搜索keyword是按照整体搜索,所以创建keyword字段的索引时是不进行分词的,比如:邮政编码、手机号码、身份证等。keyword字段通常用于过虑、排序、聚合等。

5.2.2.1测试

更改映射:

  1. {
  2. "properties": {
  3. "studymodel": {
  4. "type": "keyword"
  5. },
  6. "name": {
  7. "type": "keyword"
  8. }
  9. }
  10. }

插入文档:

  1. {
  2. "name": "java编程基础",
  3. "description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
  4. "pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
  5. "studymodel": "201001"
  6. }

根据studymodel查询文档

搜索:http://localhost:9200/xc_course/_search?q=name:java

name是keyword类型,所以查询方式是精确查询。

5.2.3 date日期类型

日期类型不用设置分词器。

通常日期类型的字段用于排序。

1)format

通过format设置日期格式

例子:

下边的设置允许date字段存储年月日时分秒、年月日及毫秒三种格式。

  1. {
  2. "properties": {
  3. "timestamp": {
  4. "type": "date",
  5. "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
  6. }
  7. }
  8. }

插入文档:

Post :http://localhost:9200/xc_course/doc/3

  1. {
  2. "name": "spring开发基础",
  3. "description": "spring 在java领域非常流行,java程序员都在用。",
  4. "studymodel": "201001",
  5. "pic":"group1/M00/00/01/wKhlQFqO4MmAOP53AAAcwDwm6SU490.jpg",
  6. "timestamp":"2018‐07‐04 18:28:58"
  7. }

6 数值类型

下边是ES支持的数值类型

1、尽量选择范围小的类型,提高搜索效率

2、对于浮点数尽量用比例因子,比如一个价格字段,单位为元,我们将比例因子设置为100这在ES中会按分存储,映射如下:

  1. "price": {
  2. "type": "scaled_float",
  3. "scaling_factor": 100
  4. }

由于比例因子为100,如果我们输入的价格是23.45则ES中会将23.45乘以100存储在ES中。

如果输入的价格是23.456,ES会将23.456乘以100再取一个接近原始值的数,得出2346。

使用比例因子的好处是整型比浮点型更易压缩,节省磁盘空间。

如果比例因子不适合,则从下表选择范围小的去用:

7 环境搭建(创建搜索工程)

1.搜索工程pom.xml
  1. <dependency>
  2. <groupId>org.elasticsearch.client</groupId>
  3. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  4. <version>6.2.1</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.elasticsearch</groupId>
  8. <artifactId>elasticsearch</artifactId>
  9. <version>6.2.1</version>
  10. </dependency>
2.配置文件
  1. es:
  2. host: 127.0.0.1:9200
  3. server:
  4. port: 1400
3.配置类
  1. import org.apache.http.HttpHost;
  2. import org.elasticsearch.client.RestClient;
  3. import org.elasticsearch.client.RestHighLevelClient;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. @Configuration
  8. public class ElasticsearchConfig {
  9. @Value("${xc.elasticsearch.hostlist}")
  10. private String hostlist;
  11. @Bean
  12. public RestHighLevelClient restHighLevelClient() {
  13. //解析hostlist配置信息
  14. String[] split = hostlist.split(",");
  15. //创建HttpHost数组,其中存放es主机和端口的配置信息
  16. HttpHost[] httpHostArray = new HttpHost[split.length];
  17. for (int i = 0; i < split.length; i++) {
  18. String item = split[i];
  19. httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
  20. }
  21. //创建RestHighLevelClient客户端
  22. return new RestHighLevelClient(RestClient.builder(httpHostArray));
  23. }
  24. //项目主要使用RestHighLevelClient,对于低级的客户端暂时不用
  25. @Bean
  26. public RestClient restClient() {
  27. //解析hostlist配置信息
  28. String[] split = hostlist.split(",");
  29. //创建HttpHost数组,其中存放es主机和端口的配置信息
  30. HttpHost[] httpHostArray = new HttpHost[split.length];
  31. for (int i = 0; i < split.length; i++) {
  32. String item = split[i];
  33. httpHostArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");
  34. }
  35. return RestClient.builder(httpHostArray).build();
  36. }
  37. }
4 商品搜索创建映射

4.1使用请求发送创建索引库

  1. {
  2. "properties": {
  3. "sn": {
  4. "type": "text"
  5. },
  6. "name": {
  7. "type": "text",
  8. "analyzer": "ik_max_word",
  9. "search_analyzer": "ik_smart"
  10. },
  11. "price": {
  12. "type": "float"
  13. },
  14. "num": {
  15. "type": "integer"
  16. },
  17. "alert_num": {
  18. "type": "integer"
  19. },
  20. "image": {
  21. "type": "text"
  22. },
  23. "images": {
  24. "type": "text"
  25. },
  26. "weight": {
  27. "type": "integer"
  28. },
  29. "create_time": {
  30. "type": "date",
  31. "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
  32. },
  33. "update_time": {
  34. "type": "date",
  35. "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd"
  36. },
  37. "spu_id": {
  38. "type": "text"
  39. },
  40. "category_id": {
  41. "type": "integer"
  42. },
  43. "category_name": {
  44. "type": "keyword"
  45. },
  46. "brand_name": {
  47. "type": "keyword"
  48. },
  49. "spec": {
  50. "type": "keyword"
  51. },
  52. "sale_num": {
  53. "type": "integer"
  54. },
  55. "comment_num": {
  56. "type": "integer"
  57. },
  58. "status": {
  59. "type": "keyword"
  60. },
  61. "version": {
  62. "type": "integer"
  63. },
  64. "specMap":{
  65. "properties":{
  66. "test":{
  67. "type": "keyword"
  68. }
  69. }
  70. }
  71. }
  72. }

4.2使用代码创建索引库

  1. public void createIndex() throws Exception {
  2. CreateIndexRequest request = new CreateIndexRequest("tb_sku", Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0").build());
  3. request.mapping("doc", "{\n" +
  4. "\t\"properties\": {\n" +
  5. "\t\t\"sn\": {\n" +
  6. "\t\t\t\"type\": \"text\"\n" +
  7. "\t\t},\n" +
  8. "\t\t\"name\": {\n" +
  9. "\t\t\t\"type\": \"text\",\n" +
  10. "\t\t\t\"analyzer\": \"ik_max_word\",\n" +
  11. "\t\t\t\"search_analyzer\": \"ik_smart\"\n" +
  12. "\t\t},\n" +
  13. "\t\t\"price\": {\n" +
  14. "\t\t\t\"type\": \"float\"\n" +
  15. "\t\t},\n" +
  16. "\t\t\"num\": {\n" +
  17. "\t\t\t\"type\": \"integer\"\n" +
  18. "\t\t},\n" +
  19. "\t\t\"alert_num\": {\n" +
  20. "\t\t\t\"type\": \"integer\"\n" +
  21. "\t\t},\n" +
  22. "\t\t\"image\": {\n" +
  23. "\t\t\t\"type\": \"text\"\n" +
  24. "\t\t},\n" +
  25. "\t\t\"images\": {\n" +
  26. "\t\t\t\"type\": \"text\"\n" +
  27. "\t\t},\n" +
  28. "\t\t\"weight\": {\n" +
  29. "\t\t\t\"type\": \"integer\"\n" +
  30. "\t\t},\n" +
  31. "\t\t\"create_time\": {\n" +
  32. "\t\t\t\"type\": \"date\",\n" +
  33. "\t\t\t\"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd\"\n" +
  34. "\t\t},\n" +
  35. "\t\t\"update_time\": {\n" +
  36. "\t\t\t\"type\": \"date\",\n" +
  37. "\t\t\t\"format\": \"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd\"\n" +
  38. "\t\t},\n" +
  39. "\t\t\"spu_id\": {\n" +
  40. "\t\t\t\"type\": \"text\"\n" +
  41. "\t\t},\n" +
  42. "\t\t\"category_id\": {\n" +
  43. "\t\t\t\"type\": \"integer\"\n" +
  44. "\t\t},\n" +
  45. "\t\t\"category_name\": {\n" +
  46. "\t\t\t\"type\": \"keyword\"\n" +
  47. "\t\t},\n" +
  48. "\t\t\"brand_name\": {\n" +
  49. "\t\t\t\"type\": \"keyword\"\n" +
  50. "\t\t},\n" +
  51. "\t\t\"spec\": {\n" +
  52. "\t\t\t\"type\": \"keyword\"\n" +
  53. "\t\t},\n" +
  54. "\t\t\"sale_num\": {\n" +
  55. "\t\t\t\"type\": \"integer\"\n" +
  56. "\t\t},\n" +
  57. "\t\t\"comment_num\": {\n" +
  58. "\t\t\t\"type\": \"integer\"\n" +
  59. "\t\t},\n" +
  60. "\t\t\"status\": {\n" +
  61. "\t\t\t\"type\": \"keyword\"\n" +
  62. "\t\t},\n" +
  63. "\t\t\"version\": {\n" +
  64. "\t\t\t\"type\": \"integer\"\n" +
  65. "\t\t},\n" +
  66. "\t\t\"specMap\":{\n" +
  67. "\t\t\t\"properties\":{\n" +
  68. "\t\t\t\t\"颜色\":{\n" +
  69. "\t\t\t\t\t\"type\": \"keyword\"\n" +
  70. "\t\t\t\t},\n" +
  71. "\t\t\t\t\"版本\":{\n" +
  72. "\t\t\t\t\t\"type\": \"keyword\"\n" +
  73. "\t\t\t\t},\n" +
  74. "\t\t\t\t\"尺码\":{\n" +
  75. "\t\t\t\t\t\"type\": \"keyword\"\n" +
  76. "\t\t\t\t},\n" +
  77. "\t\t\t\t\"内存\":{\n" +
  78. "\t\t\t\t\t\"type\": \"keyword\"\n" +
  79. "\t\t\t\t}\n" +
  80. "\t\t\t}\n" +
  81. "\t\t}\n" +
  82. "\t}\n" +
  83. "}", XContentType.JSON);
  84. CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
  85. System.out.println(response.isAcknowledged());
  86. }

4.3从数据库批量存入索引库中

  1. @Override
  2. public void importData() throws Exception {
  3. Class.forName("com.mysql.jdbc.Driver");
  4. Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/shop_goods?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8", "root", "abc123");
  5. PreparedStatement pstm = connection.prepareStatement("select * from tb_sku");
  6. ResultSet rs = pstm.executeQuery();
  7. while (rs.next()) {
  8. Map<String, Object> jsonMap = new HashMap<>();
  9. jsonMap.put("sn", rs.getString("sn"));
  10. jsonMap.put("name", rs.getString("name"));
  11. jsonMap.put("price", rs.getFloat("price"));
  12. jsonMap.put("num", rs.getInt("num"));
  13. jsonMap.put("alert_num", rs.getInt("alert_num"));
  14. jsonMap.put("image", rs.getString("image"));
  15. jsonMap.put("images", rs.getString("images"));
  16. jsonMap.put("weight", rs.getInt("weight"));
  17. jsonMap.put("spu_id", rs.getString("spu_id"));
  18. jsonMap.put("category_id", rs.getInt("category_id"));
  19. jsonMap.put("category_name", rs.getString("category_name"));
  20. jsonMap.put("brand_name", rs.getString("brand_name"));
  21. jsonMap.put("create_time", rs.getDate("create_time").toString());
  22. jsonMap.put("update_time", rs.getDate("update_time").toString());
  23. jsonMap.put("spec", rs.getString("spec"));
  24. jsonMap.put("sale_num", rs.getInt("sale_num"));
  25. jsonMap.put("comment_num", rs.getInt("comment_num"));
  26. jsonMap.put("status", rs.getString("status"));
  27. jsonMap.put("version", rs.getInt("version"));
  28. Map specMap = JSON.parseObject(rs.getString("spec"), Map.class);
  29. jsonMap.put("specMap", specMap);
  30. IndexRequest indexRequest = new IndexRequest("tb_sku", "doc", rs.getString("id"));
  31. indexRequest.source(jsonMap);
  32. IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);
  33. System.out.println(response);
  34. }
  35. }

4.4 使用javaApi方式组合查询

  1. @Override
  2. public Map<String, Object> search(Map<String, String> param) throws Exception {
  3. Map<String, Object> searchMap = new HashMap<>();
  4. SearchRequest searchRequest = new SearchRequest("tb_sku");
  5. searchRequest.types("doc");
  6. SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
  7. String keyword = param.get("keyword");
  8. if (StringUtils.isEmpty(keyword)) {
  9. keyword = "华为";
  10. }
  11. searchSourceBuilder.aggregation(AggregationBuilders.terms("cateGroup").field("category_name")).size(50);
  12. searchSourceBuilder.aggregation(AggregationBuilders.terms("brandGroup").field("brand_name")).size(50);
  13. searchSourceBuilder.aggregation(AggregationBuilders.terms("specGroup").field("spec")).size(50);
  14. MultiMatchQueryBuilder name = QueryBuilders.multiMatchQuery(keyword, "name");
  15. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  16. boolQueryBuilder.must(name);
  17. for (String key : param.keySet()) {
  18. if (key.startsWith("spec_")) {
  19. boolQueryBuilder.filter(QueryBuilders.termQuery("specMap." + key.substring(5) + ".keyword", param.get(key)));
  20. }
  21. }
  22. //设置高亮对象
  23. HighlightBuilder highlightBuilder = new HighlightBuilder();
  24. highlightBuilder.preTags("<div style='color:red;'>");
  25. highlightBuilder.postTags("</div>");
  26. highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
  27. searchSourceBuilder.highlighter(highlightBuilder);
  28. searchSourceBuilder.query(boolQueryBuilder);
  29. searchRequest.source(searchSourceBuilder);
  30. SearchResponse search = client.search(searchRequest);
  31. Terms cateTerms = search.getAggregations().get("cateGroup");
  32. List<String> cateGroup = termsLIst(cateTerms);
  33. Terms brandTerms = search.getAggregations().get("brandGroup");
  34. List<String> brandGroup = termsLIst(brandTerms);
  35. Terms specTerms = search.getAggregations().get("specGroup");
  36. Map<String, Set<String>> specMap = termsMap(specTerms);
  37. SearchHits searchHits = search.getHits();
  38. SearchHit[] hits = searchHits.getHits();
  39. List<TbSkuEntity> list = new ArrayList<>();
  40. for (SearchHit hit : hits) {
  41. String id = hit.getId();
  42. Map<String, Object> data = hit.getSourceAsMap();
  43. data.put("id", id);
  44. String json = JSON.toJSONString(data);
  45. TbSkuEntity tbSkuModel = JSON.parseObject(json, TbSkuEntity.class);
  46. Map<String, HighlightField> highlightFields = hit.getHighlightFields();
  47. StringBuffer nameBuf = new StringBuffer();
  48. if (highlightFields != null) {
  49. HighlightField names = highlightFields.get("name");
  50. if (names != null) {
  51. Text[] fragments = names.getFragments();
  52. for (Text fragment : fragments) {
  53. nameBuf.append(fragment.toString());
  54. }
  55. tbSkuModel.setName(nameBuf.toString());
  56. }
  57. }
  58. list.add(tbSkuModel);
  59. }
  60. searchMap.put("data", list);
  61. searchMap.put("cateList", cateGroup);
  62. searchMap.put("brandList", brandGroup);
  63. searchMap.put("specMap", specMap);
  64. return searchMap;
  65. }
  66. private List<String> termsLIst(Terms terms) {
  67. List<String> list = new ArrayList<>();
  68. for (Terms.Bucket bucket : terms.getBuckets()) {
  69. list.add(bucket.getKeyAsString());
  70. }
  71. return list;
  72. }
  73. private Map<String, Set<String>> termsMap(Terms terms) {
  74. Map<String, Set<String>> specMap = new HashMap<>();
  75. List<Map<String, String>> list = new ArrayList<>();
  76. for (Terms.Bucket bucket : terms.getBuckets()) {
  77. String keyAsString = bucket.getKeyAsString();
  78. Map map = JSON.parseObject(keyAsString, Map.class);
  79. list.add(map);
  80. }
  81. for (Map<String, String> map : list) {
  82. for (String key : map.keySet()) {
  83. String value = map.get(key);
  84. Set<String> strings = specMap.get(key);
  85. if (ObjectUtils.isEmpty(strings)) {
  86. strings = new HashSet<>();
  87. }
  88. strings.add(value);
  89. specMap.put(key, strings);
  90. }
  91. }
  92. return specMap;
  93. }

8 启动ES

进入bin目录,在cmd下运行:elasticsearch.bat
浏览器输入:http://localhost:9200
显示结果如下(配置不同内容则不同)说明ES启动成功:

9 运行效果图

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/802335
推荐阅读
相关标签
  

闽ICP备14008679号