当前位置:   article > 正文

ES搜索学习_elastic search 时间间隔搜索

elastic search 时间间隔搜索

1、搜索分类

 

  • 顺序扫描:eg:使用like模糊搜索,select * from user where name like "%林%"
  • 全文检索:

2、全文检索

  搜索原理概括:

  • 内容爬取,停顿词过滤。eg:一些无用的像“的”,“了”子类的语气词/连接词
  • 内容分词,提取关键字
  • 根据关键词建立倒排索引
  • 用户输入关键词进行搜索       

3、倒排索引

索引就类似于目录,平时使用的索引都是通过主键定位到数据,倒排索引刚好相反,就是通过数据定位到主键

正向索引

idnamecontent
1lin01内容1
2lin02内容2
3lin01内容3
4lin某某内容2

通过id可以查询到name/content

反向索引

关键词id
lin011,3
内容22,4

把name与content的字段抽取关键词。通过这个关键词搜索的时候,那么这个关键词就有可能出现在name/content字段内容中。

Elasticsearch 与 Mysql 对比:

        ES 里的 Index 可以看做一个库,而 Types 相当于表, Documents 则相当于表的行。这里 Types 的概念已经被逐渐弱化, Elasticsearch 6.X 中,一个 index 下已经只能包含一个type, Elasticsearch 7.X 中, Type 的概念已经被删除了。

4、ElasticSearch简介

ElasticSearch是什么:简称ES,是一个分布式、RESTful风格的搜索和数据分析引擎。

优势:

  • 完美封装了Lucene核心库,设计了友好的Restful-API,开箱即用
  • 分片与副本机制,只解决了集群下性能与高可用问题

ES主要几个版本特性:

5.x版本(大转折)
发布时间:2016.10.26
主要特性
Lucene 6.x 的支持,磁盘空间少一半;索引时间少一半;查询性能提升25%;支持IPV6。
Internal engine级别移除了用于避免同一文档并发更新的竞争锁,带来15%-20%的性能提升
提供了第一个Java原生的REST客户端SDK IngestNode
提供了 Painless 脚本,代替Groovy脚本
新增了Profile API
新增了Rollover API
新增Reindex
提供了第一个Java原生的REST客户端SDK,基于HTTP协议的客户端对Elasticsearch的依赖解耦,没有jar包冲突,提供了集群节点自动发现、日志处理、节点请求失败自动进行请求轮询,充分发挥Elasticsearch的高可用能力
引入新的字段类型 Text/Keyword 来替换 String
限制索引请求大小,避免大量并发请求压垮 ES
限制单个请求的 shards 数量,默认 1000 个
仅支持非root用户启动


6.x版本
发布时间:2017.08.31
主要特性
稀疏性 Doc Values 的支持
Index sorting,即索引阶段的排序
Removal of types,在 6.0 里面,开始不支持一个 index 里面存在多个 type
已经关闭的索引将也支持 replica 的自动处理,确保数据可靠
Load aware shard routing, 基于负载的请求路由,目前的搜索请求是全节点轮询,那么性能最慢的节点往往会造成整体的延迟增加,新的实现方式将基于队列的耗费时间自动调节队列长度,负载高的节点的队列长度将减少,让其他节点分摊更多的压力,搜索和索引都将基于这种机制。
顺序号的支持,每个 es 的操作都有一个顺序编号(类似增量设计)无缝滚动升级


7.x版本
发布时间:2019.04.10
主要特性
集群连接变化:TransportClient被废弃以至于es7的java代码,只能使用restclient。对于java编程,建议采用 High-level-rest-client 的方式操作ES集群
ES程序包默认打包jdk
Lucene9.0的支持
正式废除单个索引下多Type的支持,es6时,官方就提到了es7会删除type,并且es6时已经规定每一个index只能有一个type。在es7中使用默认的_doc作为type,官方说在8.x版本会彻底移除type。,api请求方式也发送变化,如获得某索引的某ID的文档:GET index/_doc/id其中index和id为具体的值
7.1开始,Security功能免费使用
ECK-ElasticSearch Operator on Kubernetes,支持k8s
支持Zen2 是 Elasticsearch 的全新集群协调层,提高了可靠性、性能和用户体验,变得更快、更安全,并更易于使用
Weak-AND算法提高查询性能
默认的Primary Shared数从5改为1,避免Over Sharding
间隔查询(Intervals queries) 某些搜索用例(例如,法律和专利搜索)引入了查找单词或短语彼此相距一定距离的记录的需要。 Elasticsearch 7.0中的间隔查询引入了一种构建此类查询的全新方式,与之前的方法(跨度查询span queries)相比,使用和定义更加简单。 与跨度查询相比,间隔查询对边缘情况的适应性更强
支持arm平台的包下载,包括kibana,logstash

5、安装ES(Linux-centos7)

ES版本下载地址:https://www.elastic.co/cn/downloads/past-releases#elasticsearch

找到对应版本下载 

注:ES不允许使用root账号启动服务,当前账号是root 就要用 su "账户名" eg:su es,没有另外一个账号就需要创建一个

# 创建用户并赋予相应的权限

adduser es

passwd es

chown -R es:es .

使用7.x以上的ES可以使用自带的jdk环境,环境配置:

        注意yum -y install vim*    安装vim

        1、输入命令 echo $ES_JAVA_HOME  如有显示出路径,说明已经进行了配置,否则继续下一步。

        2、vim /etc/profile   在最下面添加,修改配置:

export ES_JAVA_HOME=/usr/local/es/elasticsearch-7.17.3/jdk
export ES_JRE_HOME=$ES_JAVA_HOME/jre
export CLASSPATH=$ES_JRE_HOME/lib:$ES_JRE_HOME/lib:$CLASSPATH
export PATH=$ES_JAVA_HOME/bin:$ES_JRE_HOME/bin:$PATH

        3、 vim config/elasticsearch.yml 文件修改

# 加入如下配置

network.host: 0.0.0.0     #ES开启远程访问
cluster.name: elasticsearch
node.name: node-1
http.port: 9200
cluster.initial_master_nodes: ["node-1"]

        4、修改虚拟机jvm堆内存大小 vim config/jvm.options 

-Xms1g

-Xmx1g

        5、修改/etc/security/limits.conf

# 在文件末尾中增加下面内容
# 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536

        6、修改/etc/security/limits.d/20-nproc.conf

# 在文件末尾中增加下面内容
# 每个进程可以打开的文件数的限制
es soft nofile 65536
es hard nofile 65536
# 操作系统级别对每个用户创建的进程数的限制
* hard nproc 4096
# 注: * 带表 Linux 所有用户名称

        7、修改/etc/sysctl.conf

# 在文件中增加下面内容
# 一个进程可以拥有的 VMA(虚拟内存区域)的数量,默认值为 65536
vm.max_map_count=655360

        8、修改完sysctl.conf 之后 需要重新加载

sysctl -p

        9、默认配置,至少需要配置  discovery.seed_hosts / discovery.seed_providers / cluster.initial_master_nodes

discovery.seed_hosts: ["222.186.173.176"]  #自己linux的地址

# discovery.seed_providers:           基于配置文件配置集群主机列表
cluster.initial_master_nodes: ["node-1"]   #启动时初始化的参与选主的node,生产环境必填

启动ES

#非root用户 启动ES

bin/elasticsearch

# -d 后台启动

bin/elasticsearch -d

6、分词器(ik)插件

下载:https://github.com/medcl/elasticsearch-analysis-ik/releases 需要找到对应es的版本(版本相同)

下载完之后解压到es文件夹下的plugins目录下的ik目录(新建一个ik目录)

 注:在线下载到这个文件夹下时,记得要把压缩包删除


自定义词库:

1:现在对应的es版本的ik分词器的 jdbc-reload.properties 配置中配置对应的数据库地址:

2:添加热更新线程HotDictReloadThread

  1. public class HotDictReloadThread implements Runnable {
  2. private static final Logger LOGGER = ESPluginLoggerFactory.getLogger(HotDictReloadThread.class.getName());
  3. @Override
  4. public void run() {
  5. while(true) {
  6. LOGGER.info("[==========]reload hot dict from mysql......");
  7. Dictionary.getSingleton().reLoadMainDict();
  8. }
  9. }
  10. }

 并且需要启动热词字典加载线程,在 Dictionary 原文件中修改(找到 initial 方法中添加)

3:加载自定义数据库拓展词典到主词库表(在  Dictionary类中添加 loadExtendDictFromMysql 加载拓展词方法 与 loadStopDictFromMysql 加载停用词方法)

  1. public void loadExtendDictFromMysql(){
  2. Connection connection = null;
  3. Statement statement = null;
  4. ResultSet resultSet = null;
  5. try{
  6. Path file = PathUtils.get(getDictRoot(),"jdbc-reload.properties");
  7. props.load(new FileInputStream(file.toFile()));
  8. logger.info("loading jdbc-reload.properties");
  9. for (Object key : props.keySet()) {
  10. logger.info(key + "=" + props.getProperty(String.valueOf(key)));
  11. }
  12. logger.info(" hot dict " + props.getProperty("jdbc.reload.extend.sql"));
  13. connection = DriverManager.getConnection(
  14. props.getProperty("jdbc.url"),
  15. props.getProperty("jdbc.user"),
  16. props.getProperty("jdbc.password"));
  17. statement = connection.createStatement();
  18. resultSet = statement.executeQuery(props.getProperty("jdbc.reload.extend.sql"));
  19. while (resultSet.next()){
  20. // 加载扩展词典数据到主内存词典中
  21. String theWord = resultSet.getString("word");
  22. logger.info(theWord);
  23. _MainDict.fillSegment(theWord.trim().toLowerCase().toCharArray());
  24. }
  25. // 加载时间
  26. Thread.sleep(Integer.valueOf(String.valueOf(props.get("jdbc.reload.interval"))));
  27. }catch (Exception e){
  28. logger.error("[Extend Dict Loading] "+ e);
  29. }finally {
  30. if(resultSet != null){
  31. try {
  32. statement.close();
  33. } catch (SQLException e) {
  34. logger.error("[Extend Dict Loading] " + e);
  35. }
  36. }
  37. if(connection != null){
  38. try {
  39. connection.close();
  40. } catch (SQLException e) {
  41. logger.error("[Extend Dict Loading] " + e);
  42. }
  43. }
  44. }
  45. }
  46. public void loadStopDictFromMysql(){
  47. // 建立主词典实例
  48. _StopWords = new DictSegment((char) 0);
  49. Connection connection = null;
  50. Statement statement = null;
  51. ResultSet resultSet = null;
  52. try{
  53. Path file = PathUtils.get(getDictRoot(),"jdbc-reload.properties");
  54. props.load(new FileInputStream(file.toFile()));
  55. logger.info("loading jdbc-reload.properties");
  56. for (Object key : props.keySet()) {
  57. logger.info(key + "=" + props.getProperty(String.valueOf(key)));
  58. }
  59. logger.info(" stop dict " + props.getProperty("jdbc.reload.stop.sql"));
  60. connection = DriverManager.getConnection(
  61. props.getProperty("jdbc.url"),
  62. props.getProperty("jdbc.user"),
  63. props.getProperty("jdbc.password"));
  64. statement = connection.createStatement();
  65. resultSet = statement.executeQuery(props.getProperty("jdbc.reload.stop.sql"));
  66. while (resultSet.next()){
  67. // 加载扩展词典数据到主内存词典中
  68. String theWord = resultSet.getString("word");
  69. logger.info(theWord);
  70. _StopWords.fillSegment(theWord.trim().toLowerCase().toCharArray());
  71. }
  72. // 加载时间
  73. Thread.sleep(Integer.valueOf(String.valueOf(props.get("jdbc.reload.interval"))));
  74. }catch (Exception e){
  75. logger.error("[Stop Dict Loading] "+ e);
  76. }finally {
  77. if(resultSet != null){
  78. try {
  79. statement.close();
  80. } catch (SQLException e) {
  81. logger.error("[Stop Dict Loading] " + e);
  82. }
  83. }
  84. if(connection != null){
  85. try {
  86. connection.close();
  87. } catch (SQLException e) {
  88. logger.error("[Stop Dict Loading] " + e);
  89. }
  90. }
  91. }
  92. }

4:在 loadMainDict() 中添加自定义的加载拓展词的方法

5:在loadStopWordDict() 方法中添加自定义的加载停止词的方法

6:通过maven打包,

 注意:我这里使用的是es自带的jdk,所以要把ip和端口开通socket网络链接权限

 这个很重要!!!

到 es自带的 jdk/lib/security/default.policy文件中配置:

 

若不是使用es自带的jdk,那么常见的报错就是java.lang.ExceptionInInitializerError: null …access denied (“java.lang.RuntimePermission” “setContextClassLoader”)---配置内容位置相同

解决:
这是因为jdk权限不够

jdk14在/var/local/jdk-14.0.2/lib/security/default.policy中的grant{}里添加
jdk8是在/var/local/jdk1.8.0_271/jre/lib/security/java.policy中的grant{}里添加

permission java.lang.RuntimePermission "setContextClassLoader";

7、索引操作

创建索引:索引命名必须小写,不能以下划线开头

#创建索引     注:对比关系型数据库,创建索引就等同于创建数据库。

PUT  /es_db 

#创建索引可以设置分片数和副本数

PUT  /es_db

{

        "setting" : {

                "number_of_shards" : 3,

                "number_of_replicas" : 2

        }

}

#查询索引

GET  /es_db

#查询索引是否存在

HEAD  /es_db

#删除索引

DELETE  /ed_db

#关闭索引

POST  /es_db/_close

#打开索引

POST  /es_db/_open

#创建文档,指定id

PUT /es_db/_doc/1

{

        "name":"张三",

        "sex":1,

        "age":25,

        "address":"浙江杭州",

        "remark":"初学es"

}

#创建文档,指定id
PUT /es_db/_create/2
{
  "name":"李四",
  "sex":2,
  "age":18,
  "address":"浙江杭州",
  "remark":"初学es进阶"
}

#查询文档前10条信息内容
GET /es_db/_doc/_search

#查询对应id下的某一些信息
GET /es_db/_doc/1/_source

8、java-API操作elasticsearch

首先在pom中导入elasticsearch所需要的三个包

  1. <!-- 使用elasticsearch必须导入的三个包 -->
  2. <dependency>
  3. <groupId>org.elasticsearch.client</groupId>
  4. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  5. <version>7.1.0</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.elasticsearch.client</groupId>
  9. <artifactId>elasticsearch-rest-client</artifactId>
  10. <version>7.1.0</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.elasticsearch</groupId>
  14. <artifactId>elasticsearch</artifactId>
  15. <version>7.1.0</version>
  16. </dependency>
  • 创建索引

  1. import org.apache.http.HttpHost;
  2. import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
  3. import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestClient;
  6. import org.elasticsearch.client.RestHighLevelClient;
  7. import java.io.IOException;
  8. public class CreateIndex {
  9. public static void main(String[] args) throws IOException {
  10. // 创建客户端对象
  11. RestHighLevelClient client = new RestHighLevelClient(
  12. RestClient.builder(new HttpHost("localhost", 9200, "http")));
  13. // 创建索引 - 请求对象
  14. CreateIndexRequest request = new CreateIndexRequest("user2");
  15. // 发送请求,获取响应
  16. CreateIndexResponse response = client.indices().create(request,
  17. RequestOptions.DEFAULT);
  18. boolean acknowledged = response.isAcknowledged();
  19. // 响应状态
  20. System.out.println("操作状态 = " + acknowledged);
  21. // 关闭客户端连接
  22. client.close();
  23. }
  24. }
  • 查询索引

  1. import org.apache.http.HttpHost;
  2. import org.elasticsearch.client.RequestOptions;
  3. import org.elasticsearch.client.RestClient;
  4. import org.elasticsearch.client.RestHighLevelClient;
  5. import org.elasticsearch.client.indices.GetIndexRequest;
  6. import org.elasticsearch.client.indices.GetIndexResponse;
  7. import java.io.IOException;
  8. public class SearchIndex {
  9. public static void main(String[] args) throws IOException {
  10. // 创建客户端对象
  11. RestHighLevelClient client = new RestHighLevelClient(
  12. RestClient.builder(new HttpHost("localhost", 9200, "http")));
  13. // 查询索引 - 请求对象
  14. GetIndexRequest request = new GetIndexRequest("user2");
  15. // 发送请求,获取响应
  16. GetIndexResponse response = client.indices().get(request,
  17. RequestOptions.DEFAULT);
  18. System.out.println("aliases:"+response.getAliases());
  19. System.out.println("mappings:"+response.getMappings());
  20. System.out.println("settings:"+response.getSettings());
  21. client.close();
  22. }
  23. }
  •  删除索引

  1. import org.apache.http.HttpHost;
  2. import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
  3. import org.elasticsearch.action.support.master.AcknowledgedResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.client.RestClient;
  6. import org.elasticsearch.client.RestHighLevelClient;
  7. import java.io.IOException;
  8. public class DeleteIndex {
  9. public static void main(String[] args) throws IOException {
  10. RestHighLevelClient client = new RestHighLevelClient(
  11. RestClient.builder(new HttpHost("localhost", 9200, "http")));
  12. // 删除索引 - 请求对象
  13. DeleteIndexRequest request = new DeleteIndexRequest("user2");
  14. // 发送请求,获取响应
  15. AcknowledgedResponse response = client.indices().delete(request,RequestOptions.DEFAULT);
  16. // 操作结果
  17. System.out.println("操作结果 : " + response.isAcknowledged());
  18. client.close();
  19. }
  20. }
  • 写一个通用方法去连接并关闭elasticsearch

  1. import org.elasticsearch.client.RestHighLevelClient;
  2. public interface ElasticsearchTask {
  3. void doSomething(RestHighLevelClient client) throws Exception;
  4. }
  1. public class ConnectElasticsearch{
  2. public static void connect(ElasticsearchTask task){
  3. // 创建客户端对象
  4. RestHighLevelClient client = new RestHighLevelClient(
  5. RestClient.builder(new HttpHost("localhost", 9200, "http")));
  6. try {
  7. task.doSomething(client);
  8. // 关闭客户端连接
  9. client.close();
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. }

 使用这个通用方法使用lambda表达式新增一条文档数据,并且附上直接连接elasticsearch并添加数据

  1. package com.es.mian;
  2. import com.es.entity.User;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import org.apache.http.HttpHost;
  5. import org.elasticsearch.action.index.IndexRequest;
  6. import org.elasticsearch.action.index.IndexResponse;
  7. import org.elasticsearch.client.RequestOptions;
  8. import org.elasticsearch.client.RestClient;
  9. import org.elasticsearch.client.RestHighLevelClient;
  10. import org.elasticsearch.common.xcontent.XContentType;
  11. import java.io.IOException;
  12. public class InsertDoc {
  13. public static void main(String[] args) {
  14. ConnectElasticsearch.connect(client -> {
  15. // 新增文档 - 请求对象
  16. IndexRequest request = new IndexRequest();
  17. // 设置索引及唯一性标识
  18. request.index("user2").id("1001");
  19. // 创建数据对象
  20. User user = new User();
  21. user.setName("李四");
  22. user.setAge(18);
  23. user.setSex("女");
  24. ObjectMapper objectMapper = new ObjectMapper();
  25. String productJson = objectMapper.writeValueAsString(user);
  26. // 添加文档数据,数据格式为 JSON 格式
  27. request.source(productJson, XContentType.JSON);
  28. // 客户端发送请求,获取响应对象
  29. IndexResponse response = client.index(request, RequestOptions.DEFAULT);
  30. //3.打印结果信息
  31. System.out.println("_index:" + response.getIndex());
  32. System.out.println("_id:" + response.getId());
  33. System.out.println("_result:" + response.getResult());
  34. });
  35. }
  36. /*public static void main(String[] args) throws IOException {
  37. // 传入IP地址和端口号
  38. HttpHost httpHost = new HttpHost("localhost", 9200, "http");
  39. // 创建客户端对象
  40. RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(httpHost));
  41. // 1.要在指定索引下创建文档,所以要先创建索引,再创建文档
  42. IndexRequest request=new IndexRequest();
  43. // index()方法设置索引名;id()方法设置唯一id标识
  44. request.index("user2").id("10001");
  45. // 2.创建实体类对象,填充数据
  46. User user=new User();
  47. user.setName("张三");
  48. user.setAge(30);
  49. user.setSex("男");
  50. // 3.利用jackson将实体类对象转换成JSON格式字符串
  51. ObjectMapper mapper=new ObjectMapper();
  52. String userJson = mapper.writeValueAsString(user);
  53. // 4.添加文档数据,数据格式为JSON格式
  54. request.source(userJson, XContentType.JSON);
  55. // 5.发送请求,获取响应结果
  56. IndexResponse response = client.index(request, RequestOptions.DEFAULT);
  57. System.out.println("_index: "+response.getIndex());
  58. System.out.println("_id: "+response.getId());
  59. System.out.println("_result: "+response.getResult());
  60. // 一番操作后,关闭客户端连接
  61. client.close();
  62. }*/
  63. }
  • 更新操作

  1. package com.es.mian;
  2. import org.elasticsearch.action.update.UpdateRequest;
  3. import org.elasticsearch.action.update.UpdateResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. import org.elasticsearch.common.xcontent.XContentType;
  6. public class UpdateDoc {
  7. public static void main(String[] args) {
  8. ConnectElasticsearch.connect(client -> {
  9. // 修改文档 - 请求对象
  10. UpdateRequest request = new UpdateRequest();
  11. // 配置修改参数
  12. request.index("user2").id("1001");
  13. // 设置请求体,对数据进行修改
  14. request.doc(XContentType.JSON, "name", "李四-修改之后的数据");
  15. // 客户端发送请求,获取响应对象
  16. UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
  17. System.out.println("_index:" + response.getIndex());
  18. System.out.println("_id:" + response.getId());
  19. System.out.println("_result:" + response.getResult());
  20. });
  21. }
  22. }
  • 查询user2索引下面的id为1001的文档数据内容

  1. package com.es.mian;
  2. import org.elasticsearch.action.get.GetRequest;
  3. import org.elasticsearch.action.get.GetResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. public class GetDoc {
  6. public static void main(String[] args) {
  7. ConnectElasticsearch.connect(client -> {
  8. //1.创建请求对象
  9. GetRequest request = new GetRequest().index("user2").id("1001");
  10. //2.客户端发送请求,获取响应对象
  11. GetResponse response = client.get(request, RequestOptions.DEFAULT);
  12. //3.打印结果信息
  13. System.out.println("_index:" + response.getIndex());
  14. System.out.println("_type:" + response.getType());
  15. System.out.println("_id:" + response.getId());
  16. System.out.println("source:" + response.getSourceAsString());
  17. });
  18. }
  19. }
  •  删除user2索引下面id为10001的文档数据

  1. package com.es.mian;
  2. import org.elasticsearch.action.delete.DeleteRequest;
  3. import org.elasticsearch.action.delete.DeleteResponse;
  4. import org.elasticsearch.client.RequestOptions;
  5. public class DeleteDoc {
  6. public static void main(String[] args) {
  7. ConnectElasticsearch.connect(client -> {
  8. //创建请求对象
  9. DeleteRequest request = new DeleteRequest().index("user2").id("10001");
  10. //客户端发送请求,获取响应对象
  11. DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
  12. //打印信息
  13. System.out.println(response.toString());
  14. });
  15. }
  16. }

9、Kibana安装

下载对应elasticsearch的版本的kibana  eg:es版本为7.17.3 那么kibana下载7.17.3的版本 

1、下载地址:https://www.elastic.co/cn/downloads/past-releases#kibana

2、对应压缩包放到对应目录 解压:tar -zxvf

10、ElasticSearch 基本概念

关系型数据库 与 ElasticSearch

  • 在7.0之前,一个index可以设置多个Types
  • 目前Type已经被Deprecated,7.0开始,一个索引只能创建一个Type - "_doc"
  • 两者的区别

        

 文档(Document)

  • Elasticsearch 是面向文档的,文档是所有可能搜索数据的最小单位
  • 文档会被序列化成JSON格式,保存在Elasticsearch中
  • 每一个文档都有一个Unique ID
  • 一篇文档包含了一系列字段,类似于数据库表中的一条记录
  • JSON文档,格式灵活,不需要预先定义格式

批量写入

批量对文档进行写操作失通过 _bulk 的API来实现的

  • 请求方式:post
  • 请求地址:_bulk
  • 请求参数:通过_bulk操作文档,一般至少有两行参数(或偶行参数)

        -第一行参数为指定操作的类型及操作的对象(index,type和id)

        -第二行参数才是操作的数据

参数类似于:

{“actionName”:{"_index":"indexName","_type":"typeName","_id":"id"}}

{"field1":"value1","field2":"value2"}

# actionName:表示操作类型,主要操作类型有 create,index,delete和update

批量查询

        _mget批量读取

#批量读取对应index下的文档id,没有指定索引的_mget
GET _mget 

  "docs": [
      {
        "_index":"es_db",
        "_id": "1"
      },
      {
        "_index":"user2",
        "_id":"1"
      },
      {
        "_index":"user2",
        "_id":"2"

      }
    ]
}

#批量读取index为user2下的文档id,指定索引
GET /user2/_mget 

  "docs": [
      {
        "_id": "1"
      },
      {
        "_id":"2"
      },
      {
        "_id":"3"
      }
    ]
}

#进一步简化
GET /user2/_mget 

  "ids":["1","2","3"]
}

        _msearch: 在_msearch中,请求格式和bulk类似。查询一条数据需要两个对象,第一个设置index和type,第二个设置查询语句。查询语句和search相同。如果只是查询一个index,我们可以在url中带上indedx,这样,如果查询该index可以直接用空对象表示。

11、Easy-Es 的maven

 easy-es 接口官网:快速开始 | Easy-Es

 easy-es 主要是es结合了mybatis-plus,使用方式与mybatis-plus一样。

  1. <!-- 引入easy-es最新版本的依赖-->
  2. <dependency>
  3. <groupId>cn.easy-es</groupId>
  4. <artifactId>easy-es-boot-starter</artifactId>
  5. <!--这里Latest Version是指最新版本的依赖,比如2.0.0,可以通过下面的图片获取-->
  6. <version>Latest Version</version>
  7. </dependency>
  8. <!-- 排除springboot中内置的es依赖,以防和easy-es中的依赖冲突-->
  9. <dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-web</artifactId>
  12. <exclusions>
  13. <exclusion>
  14. <groupId>org.elasticsearch.client</groupId>
  15. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  16. </exclusion>
  17. <exclusion>
  18. <groupId>org.elasticsearch</groupId>
  19. <artifactId>elasticsearch</artifactId>
  20. </exclusion>
  21. </exclusions>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.elasticsearch.client</groupId>
  25. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  26. <version>7.14.0</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.elasticsearch</groupId>
  30. <artifactId>elasticsearch</artifactId>
  31. <version>7.14.0</version>
  32. </dependency>

 Elasticsearch 基础语法:

  1. BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  2. //wildcardQuery 通配符查询,支持* 任意字符串;?任意一个字符
  3. boolQuery.should(QueryBuilders.wildcardQuery("categoryId", "*"+item+"*"));
  4. //termsQuery 分词精确查询
  5. boolQuery.should(QueryBuilders.termsQuery("spuId", spuId));
  6. //matchPhraseQuery 顺序相同不是指字段值的内容完全包含关键词,而是指分词顺序相同。
  7. boolQuery.should(QueryBuilders.matchPhraseQuery("name", "黄山风景"));
  8. //注意:此时分词搜索,name 为 "安徽黄山风景区"的内容,搜索不出来,因为"安徽黄山风景区"和"黄山风景"分词,发现分词"山风"和"风景"之间还间隔了"风景区"这个分词,所以不符合条件。
  9. //解决可以设置slop解决分词间隔数量(分析:对第一条文档中的字段分词,"安徽黄山风景区"分词后发现安徽距离风景区相差两个字段,所以设置slop=2可以解决默认相隔字段为0的问题。)
  10. boolQuery.should(QueryBuilders.matchPhraseQuery("name", "黄山风景").slop(2))
  11. //matchQuery 即匹配查询。返回与提供的文本、数字、日期或布尔值匹配的文档。在匹配之前分析提供的文本。匹配查询是执行全文搜索的标准查询,包括模糊匹配选项。
  12. boolQuery.should(QueryBuilders.matchQuery("dosTitle","我爱中华"))
  13. //rangeQuery 范围查询
  14. boolQuery.should(QueryBuilders.boolQuery().must(
  15. QueryBuilders.boolQuery()
  16. //定时上架时间 大于等于当前时间
  17. .must(QueryBuilders.rangeQuery("offShelvesTime" ).gte(date.getTime()))
  18. //定时下架时间 小于等于当前时间
  19. .must(QueryBuilders.rangeQuery("putawayStartTime" ).lte(date.getTime())))
  20. );
  21. //条件写完之后,进行查询
  22. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder()
  23. //查询条件
  24. .withQuery(boolQuery)
  25. //分页
  26. .withPageable(PageRequest.of(pageNum, pageSize))
  27. //排序
  28. .withSort(sortBuilders.scoreSort().order(SortOrder.DESC));
  29. val search = restTemplate.search(nativeSearchQueryBuilder.build(), EsGoodsSpuEs.class);
  30. for (SearchHit<EsGoodsSpuEs> searchHit : search.getSearchHits()) {
  31. list.add(searchHit.getContent());
  32. }
  33. map.put("total",search.getTotalHits()); //es搜索出来的总条数
  34. map.put("list",list); //当前页数据list

重点需要注意的:

  1. 需要排序的字段,实体类型不能是 Bigdecimal 类型,否则排序会有问题(eg:字段类型为bigdecimal时,价格倒序时,价格为10.20 的商品会排在 价格为100的前面)
  2. 需要进行分词的字段 在es库中对应字段的 analyzer 要为 ik_max_word (这样在进行分词查询时,会把对应name字段分词,并且把搜索入参进行分词,然后进行匹配)

eg:"name" : {
          "type" : "text",
          "analyzer" : "ik_max_word"
        },

       3.使用matchPhraseQuery查询方法时,字段analyzer不要使用ik_max_word

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

闽ICP备14008679号