当前位置: 首页 > news >正文

知名设计公司网站虚拟机做网站有用吗

知名设计公司网站,虚拟机做网站有用吗,企业登记信息查询系统,如何进行搜索引擎的优化一 Elasticsearch介绍 1 全文检索 Elasticsearch是一个全文检索服务器 全文检索是一种非结构化数据的搜索方式 结构化数据#xff1a;指具有固定格式固定长度的数据#xff0c;如数据库中的字段。 非结构化数据#xff1a;指格式和长度不固定的数据#xff0c;如电商网站…一 Elasticsearch介绍 1 全文检索 Elasticsearch是一个全文检索服务器 全文检索是一种非结构化数据的搜索方式 结构化数据指具有固定格式固定长度的数据如数据库中的字段。 非结构化数据指格式和长度不固定的数据如电商网站的商品详情。 结构化数据一般存入数据库使用sql语句即可快速查询。但由于非结构化数据的数据量大且格式不固定我们需要采用全文检索的方式进行搜索。全文检索通过建立倒排索引加快搜索效率。 2 倒排索引 索引 将数据中的一部分信息提取出来重新组织成一定的数据结构我们可以根据该结构进行快速搜索这样的结构称之为索引。 索引即目录例如字典会将字的拼音提取出来做成目录通过目录即可快速找到字的位置。 索引分为正排索引和倒排索引。 正排索引正向索引 将文档id建立为索引通过id快速可以快速查找数据。如数据库中的主键就会创建正排索引。 倒排索引反向索引 非结构化数据中我们往往会根据关键词查询数据。此时我们将数据中的关键词建立为索引指向文档数据这样的索引称为倒排索引。 创建倒排索引流程 3 Elasticsearch数据结构 文档Document文档是可被查询的最小数据单元一个 Document 就是一条数据。类似于关系型数据库中的记录的概念。 类型Type具有一组共同字段的文档定义成一个类型类似于关系型数据库中的数据表的概念。 索引Index索引是多种类型文档的集合类似于关系型数据库中的库的概念。 域Fied文档由多个域组成类似于关系型数据库中的字段的概念。 Elasticsearch跟关系型数据库中概念的对比 JAVA项目实体类对象属性ESIndexTypeDocumentFiledMysqlDatabaseTableRowColumn 注ES7.X之后删除了type的概念一个索引不会代表一个库 而是代表一张表。本文中使用ES7.17所以目前的ES中概念对比为 JAVA项目实体类对象属性ESIndexDocumentFiledMysqlDatabaseTableRowColumn 二 Elasticsearch安装 1 安装ES服务 准备工作 准备一台搭载有CentOS7系统的虚拟机使用XShell连接虚拟机关闭防火墙方便访问ES #关闭防火墙 systemctl stop firewalld.service#禁止防火墙自启动 systemctl disable firewalld.service配置最大可创建文件数大小 #打开系统文件 vim /etc/sysctl.conf#添加以下配置 vm.max_map_count655360#配置生效 sysctl -p由于ES不能以root用户运行我们需要创建一个非root用户此 处创建一个名为es的用户 #创建用户 useradd es安装服务 使用xftp将linux版的ES上传至虚拟机解压ES #解压 tar -zxvf elasticsearch-7.17.0-linux-x86_64.tar.gz#重命名 mv elasticsearch-7.17.0 elasticsearch1#移动文件夹 mv elasticsearch1 /usr/local/#es用户取得该文件夹权限 chown -R es:es /usr/local/elasticsearch1改变文件拥有者chown 语法 chown [-R] 属主名:属组名 文件名启动ES服务 #切换为es用户 su es#进入ES安装文件夹 cd /usr/local/elasticsearch1/bin/#启动ES服务 ./elasticsearch#查询ES服务是否启动成功 curl 127.0.0.1:92002 安装kibana Kibana是一款开源的数据分析和可视化平台设计用于和 Elasticsearch协作。我们可以使用Kibana对Elasticsearch索引中的数据进行搜索、查看、交互操作。 使用xftp将将Kibana压缩文件上传到Linux虚拟机解压 tar -zxvf kibana-7.17.0-linux-x86_64.tar.gz -C /usr/local/修改配置 # 进入Kibana解压路径 cd /usr/local/kibana-7.17.0-linux-x86_64/config# 修改配置文件 vim kibana.yml# 加入以下内容 # kibana主机IP server.host: 虚拟机IP # Elasticsearch路径 elasticsearch.hosts: [http://127.0.0.1:9200]启动 kibana不能以root用户运行我们给es用户设置kibana目录的权限并使用es用户运行kibana # 给es用户设置kibana目录权限 chown -R es:es /usr/local/kibana-7.17.0-linux-x86_64/# 切换为es用户 su es# 启动kibana cd /usr/local/kibana-7.17.0-linux-x86_64/bin/ ./kibana访问kibanahttp://虚拟机IP:5601点击 Management Stack Management Index Management 可以查看es索引信息。 3 Docker安装 安装Elasticsearch 拉取镜像 docker pull elasticsearch:7.17.0启动容器 # docker容器间建立通信 docker network create elastic # 创建es容器 docker run --restartalways -p 9200:9200 -p 9300:9300 -e discovery.typesinglenode -e ES_JAVA_OPTS-Xms512m -Xmx512m --nameelasticsearch --net elastic --cpuset-cpus1 -m 1G -d elasticsearch:7.17.0安装Kibana 拉取镜像 docker pull kibana:7.17.0启动容器 docker run --name kibana --net elastic --link elasticsearch:elasticsearch -p 5601:5601 -d kibana:7.17.0访问kibanahttp://虚拟机IP:5601 三 Elasticsearch常用操作 1 索引操作 Elasticsearch是使用RESTful风格的http请求访问操作的请求参数和返回值都是Json格式的我们可以使用kibana发送http请求操作ES。 创建没有结构的索引 路径ip地址:端口号/索引名 注在kibana中所有的请求都会省略 ip地址:端口号 之后的路径我 们省略写 ip地址:端口号 请求方式PUT 举例 PUT /student为索引添加结构 POST /索引名/_mapping {properties:{域名1:{type:域的类型,store:是否存储,index:是否创建索引,analyzer:分词器},域名2:{...}} } 举例 POST /student/_mapping {properties: {id:{type:integer},name: {type: text},age: {type: integer}} }创建有结构的索引 PUT /索引名 {mappings:{properties:{域名1:{type:域的类型,store:是否单独存储,index:是否创建索引,analyzer:分词器},域名2:{...}}} } 举例 PUT /student1 {mappings: {properties: {name: {type: text},age: {type: integer}}} } 删除索引 DELETE /索引名举例: DELETE /student12 文档操作 新增/修改文档 POST /索引/_doc/[id值] {field名:field值 }注id值不写时自动生成文档idid和已有id重复时修改文档 举例 POST /student/_doc/1 {name: lxx,age: 18 }根据id查询文档 GET /索引/_doc/id值举例 GET /student/_doc/1删除文档 DELETE /索引/_doc/id值举例 DELETE /student/_doc/1根据id批量查询文档 GET /索引/_mget {docs:[{_id:id值},{_id:id值}] }举例 GET /student/_mget {docs: [{_id: 1},{_id: 2}] }查询所有文档 GET /索引/_search {query: {match_all: {}} }举例 GET /student/_search {query: {match_all: {}} }修改文档部分字段 POST /索引/_doc/id值/_update {doc:{域名:值} }注 Elasticsearch执行删除操作时ES先标记文档为deleted状态 而不是直接物理删除。当ES存储空间不足或工作空闲时才会执行物理删除操作。 Elasticsearch执行修改操作时ES不会真的修改Document中 的数据而是标记ES中原有的文档为deleted状态再创建一个 新的文档来存储数据。 举例 POST /student/_doc/1/_update {doc: {name: newLxx} }3 域的属性 index 该域是否创建索引。只有值设置为true才能根据该域的关键词查询文档。 // 根据关键词查询文档 GET /索引名/_search {query:{term:{搜索字段: 关键字}} }案例 PUT /student1 {mappings: {properties: {name: {type: text,index: true}}} }PUT /student2 {mappings: {properties: {name: {type: text,index: false}}} }POST /student1/_doc/1 {name:I love you }POST /student2/_doc/1 {name:I love you }GET /student1/_search {query:{term:{name:love}} } // 可以查询到结果GET /student2/_search {query:{term:{name:love}} } // 查询不到结果type 域的类型 核心类型具体类型字符串类型text整数类型long, integer, short, byte浮点类型double, float日期类型date布尔类型boolean数组类型array对象类型object不分词的字符串keyword store 是否单独存储。如果设置为true则该域能够单独查询。 // 单独查询某个域 GET /索引名/_search {stored_fields: [域名] }举例 PUT /student3 {mappings: {properties: {name: {type: text,store: true}}} }POST /student3/_doc/1 {name:I love you1 }POST /student3/_doc/2 {name:I love you2 }GET /student3/_search {stored_fields: [name] } 四 分词器 1 默认分词器 ES文档的数据拆分成一个个有完整含义的关键词并将关键词与文档对应这样就可以通过关键词查询文档。要想正确的分词需要选择合适的分词器。 analyzer插入文档时将text类型的字段做分词然后插入倒排索引。 search_analyzer查询时先对要查询的text类型的输入做分词再去倒排索引中搜索。 如果想要让’索引’和’查询’时使用不同的分词器ElasticSearch也是能支持的只需要在字段上加上search_analyzer参数。插入时只会去看字段有没有定义analyzer有定义的话就用定义的没定义就用es预设的。查询时会先去看字段有没有定义search_analyzer如果没有定义就去看有没有analyzer再没有定义才会去使用es预设的 standard analyzerElasticsearch默认分词器根据空格和标点符号对英文进行分词会进行单词的大小写转换。 默认分词器是英文分词器对中文的分词是一字一词。 查看分词效果 GET /_analyze {text:测试语句,analyzer:分词器 }举例 GET /_analyze {text: I love you,analyzer: standard }2 IK分词器 IKAnalyzer是一个开源的基于java语言开发的轻量级的中文分词工具包。提供了两种分词算法 ik_smart最少切分ik_max_word最细粒度划分 安装IK分词器 关闭es服务使用xftp将ik分词器上传至虚拟机 注ik分词器的版本要和es版本保持一致。 解压ik分词器到elasticsearch的plugins目录下 unzip elasticsearch-analysis-ik-7.17.0.zip -d /usr/local/elasticsearch1/plugins/analysis-ik启动ES服务 su es#进入ES安装文件夹 cd /usr/local/elasticsearch1/bin/#启动ES服务 ./elasticsearch -d测试分词器效果 GET /_analyze {text:测试语句,analyzer:ik_smart/ik_max_word } 举例 GET /_analyze {text: 湖人总冠军,analyzer: ik_smart }IK分词器词典 IK分词器根据词典进行分词词典文件在IK分词器的config目录中。(/usr/local/elasticsearch1/plugins/analysis-ik/config) main.dicIK中内置的词典。记录了IK统计的所有中文单词。IKAnalyzer.cfg.xml用于配置自定义词库。 propertiescommentIK Analyzer 扩展配置/comment!--用户可以在这里配置自己的扩展字典 --entry keyext_dictext_dict.dic/entry!--用户可以在这里配置自己的扩展停止词字典--entry keyext_stopwordsext_stopwords.dic/entry!--用户可以在这里配置远程扩展字典 --!-- entry keyremote_ext_dictwords_location/entry --!--用户可以在这里配置远程扩展停止词字典--!-- entry keyremote_ext_stopwordswords_location/entry -- /properties3 拼音分词器 拼音分词器可以将中文分成对应的全拼全拼首字母等。 安装拼音分词器 关闭es服务使用xftp将拼音分词器上传至虚拟机 注ik分词器的版本要和es版本保持一致。 解压拼音分词器到elasticsearch的plugins目录下 unzip elasticsearch-analysis-pinyin-7.17.0.zip -d /usr/local/elasticsearch1/plugins/analysis-pinyin启动ES服务 su es#进入ES安装文件夹 cd /usr/local/elasticsearch1/bin/#启动ES服务 ./elasticsearch测试分词器效果 GET /_analyze {text:测试语句,analyzer:pinyin } 举例 GET /_analyze {text: 湖人总冠军,analyzer: pinyin }4 自定义分词器 真实开发中我们往往需要对一段内容既进行文字分词又进行拼音分词此时我们需要自定义ikpinyin分词器。 创建自定义分词器 在创建索引时自定义分词器 PUT /索引名 {settings : {analysis : {analyzer : {ik_pinyin : { //自定义分词器名tokenizer:ik_max_word, // 基本分词器filter:pinyin_filter // 配置分词器过滤}},filter : { // 分词器过滤时配置另一个分词器相当于同时使用两个分词器pinyin_filter : {type : pinyin, // 另一个分词器// 拼音分词器的配置keep_separate_first_letter : false, // 是否分词每个字的首字母keep_full_pinyin :true, // 是否分词全拼keep_original : true,// 是否保留原始输入remove_duplicated_term: true // 是否删除重复项}}}},mappings:{properties:{域名1:{type:域的类型,store:是否单独存储,index:是否创建索引,analyzer:分词器},域名2:{...}}} }举例 PUT /student4 {settings: {analysis: {analyzer: {ik_pinyin: {tokenizer: ik_max_word,filter: pinyin_filter}},filter: {pinyin_filter: {type: pinyin,keep_separate_first_letter: false,keep_full_pinyin: true,keep_original: true,remove_duplicated_term: true}}}},mappings: {properties: {name: {type: text,store: true,index: true,analyzer: ik_pinyin},age: {type: integer}}} } 测试自定义分词器 GET /索引/_analyze {text: 测试语句,analyzer: ik_pinyin }举例 GET /student4/_analyze {text: 湖人总冠军,analyzer: ik_pinyin }五 Elasticsearch搜索文档 1 准备工作 Elasticsearch提供了全面的文档搜索方式在学习前我们添加一些文档数据 PUT /students {mappings: {properties: {id: {type: integer,index: true},name: {type: text,store: true,index: true,analyzer: ik_smart},info: {type: text,store: true,index: true,analyzer: ik_smart}}} } POST /students/_doc/ {id: 1,name: 百战程序员,info: I love baizhan } POST /students/_doc/ {id: 2,name: 美羊羊,info: 美羊羊是羊村最漂亮的人 } POST /students/_doc/ {id: 3,name: 懒羊羊,info: 懒羊羊的成绩不是很好 } POST /students/_doc/ {id: 4,name: 小灰灰,info: 小灰灰的年纪比较小 } POST /students/_doc/ {id: 5,name: 沸羊羊,info: 沸羊羊喜欢美羊羊 } POST /students/_doc/ {id: 6,name: 灰太狼,info: 灰太狼是小灰灰的父亲每次都会说我一定会回来的 }文档搜索 GET /索引/_search {query:{搜索方式:搜索参数} } 2 搜索方式 match_all查询所有文档 {query:{match_all:{}} }举例 GET /students/_search {query: {match_all: {}} }match全文检索。将查询条件分词后再进行搜索。 {query:{match:{搜索字段:搜索条件}} }注在搜索时关键词有可能会输入错误ES搜索提供了自动纠错功能即ES的模糊查询。使用match方式可以实现模糊查询。模糊查询对中文的支持效果一般我们使用英文数据测试模糊查询。 {query:{match:{域名:{query:搜索条件,fuzziness:最多错误字符数,不能超过2}}} }举例 GET /students/_search {query: {match: {info: 我喜欢成绩好的}} }GET /students/_search {query: {match: {info: {query: lovr,fuzziness: 1}}} }range范围搜索。对数字类型的字段进行范围搜索 {query:{range:{搜索字段:{gte:最小值,lte:最大值}}} } gt/lt:大于/小于 gte/lte:大于等于/小于等于举例 GET /students/_search {query: {range: {id: {gte: 2,lte: 4}}} }match_phrase短语检索。搜索条件不做任何分词解析在搜索字段对应的倒排索引中精确匹配。 {query:{match_phrase:{搜索字段:搜索条件}} }举例 GET /students/_search {query: {match_phrase: {info: 喜欢}} }term/terms单词/词组搜索。搜索条件不做任何分词解析在搜索字段对应的倒排索引中精确匹配 {query:{term:{ 搜索字段: 搜索条件}} } {query:{terms:{ 搜索字段: [搜索条件1,搜索条件2]}} }举例 GET /students/_search {query: {term: {info: 喜欢}} }GET /students/_search {query: {terms: {info: [喜欢,漂亮]}} }3 复合搜索 GET /索引/_search {query: {bool: {// 必须满足的条件must: [搜索方式:搜索参数,搜索方式:搜索参数],// 多个条件有任意一个满足即可should: [搜索方式:搜索参数,搜索方式:搜索参数],// 必须不满足的条件must_not:[搜索方式:搜索参数,搜索方式:搜索参数]}} }举例: GET /students/_search {query: {bool: {must: [{match: {info: 美羊羊喜欢成绩好的同学}}],must_not: [{range: {id: {gte: 1,lte: 3}}}]}} }4 结果排序 ES中默认使用相关度分数实现排序可以通过搜索语法定制化排序。 GET /索引/_search {query: 搜索条件,sort: [{字段1: {order: asc}},{字段2: {order: desc}}] }由于ES对text类型字段数据会做分词处理使用哪一个单词做排序都是不合理的所以ES中默认不允许对text类型的字段做排序。如果需要使用字符串做结果排序可以使用 keyword类型 的字段作为排序依据因为keyword字段不做分词处理。 举例: GET /students/_search {query: {match: {name: 羊}},sort: [{id: {order: desc}}] }5 分页查询 GET /索引/_search {query: 搜索条件,from: 起始下标,size: 查询记录数 }举例 GET /students/_search {query: {match_all: {}},from: 0,size: 2 }GET /students/_search {query: {match_all: {}},from: 2,size: 2 }6 高亮查询 在进行关键字搜索时搜索出的内容中的关键字会显示不同的颜色称之为高亮。 为什么在网页中关键字会显示不同的颜色我们通过开发者工具查看网页源码 我们可以在关键字左右加入标签字符串数据传入前端即可完成高亮显示ES可以对查询出的内容中关键字部分进行标签和样式的设置。 GET /索引/_search {query:搜索条件,highlight:{fields: {高亮显示的字段名: {// 返回高亮数据的最大长度fragment_size:100,// 返回结果最多可以包含几段不连续的文字number_of_fragments:5}},pre_tags:[前缀],post_tags:[后缀]}} }举例 GET /students/_search {query: {match: {info: 我喜欢成绩好的}},highlight: {fields: {info: {fragment_size: 20,number_of_fragments: 5}},pre_tags: [em],post_tags: [/em]} }7 SQL查询 在ES7之后支持SQL语句查询文档 GET /_sql?formattxt {query: SQL语句 }开源版本的ES并不支持通过Java操作SQL进行查询如果需要操 作 SQL查询则需要氪金购买白金版 六 原生JAVA操作ES 1 搭建项目 原生JAVA可以对ES的索引和文档进行操作但操作较复杂我们了解即可。 创建maven项目maven项目引入以下依赖 dependencygroupIdorg.elasticsearch/groupIdartifactIdelasticsearch/artifactIdversion7.17.0/version/dependencydependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-high-level-client/artifactIdversion7.17.0/version/dependency2 索引操作 创建空索引 //索引操作 public class IndexTest {// 创建空索引Testpublic void createIndex() throws IOException {// 1.创建客户端对象连接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 2.创建请求对象CreateIndexRequest request new CreateIndexRequest(student);// 3.发送请求CreateIndexResponse response client.indices().create(request, RequestOptions.DEFAULT);// 4.操作响应结果System.out.println(response.index());// 5.关闭客户端client.close();}外部无法访问ES的解决方案 打开Elasticsearch安装路径下config目录下的elasticsearch.yml 文件加入如下配置 discovery.seed_hosts: [host1] network.host: 0.0.0.0重新启动ES即可。 PS如果修改配置文件后启动报错: 1、max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536] 每个进程最大同时打开文件数太小 修改/etc/security/limits.conf文件增加配置用户退出后重新登录生效 * soft nofile 65536 * hard nofile 655362、max number of threads [3818] for user [hadoop] is too low, increase to at least [4096] 问题同上最大线程个数太低。 修改/etc/security/limits.conf文件增加配置用户退出后重新登录生效 * soft nproc 4096 * hard nproc 4096给索引添加结构 //给索引添加结构Testpublic void mappingIndex() throws IOException {// 1.创建客户端对象连接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 2.创建请求对象PutMappingRequest request new PutMappingRequest(student);request.source({\n \properties\: {\n \id\:{\n \type\:\integer\\n },\n \name\: {\n \type\: \text\\n },\n \age\: {\n \type\: \integer\\n }\n }\n }, XContentType.JSON);// 3.发送请求AcknowledgedResponse response client.indices().putMapping(request, RequestOptions.DEFAULT);// 4.操作响应结果System.out.println(response.isAcknowledged());// 5.关闭客户端client.close();}删除索引 // 删除索引Testpublic void deleteIndex() throws IOException {// 1.创建客户端对象连接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 2.创建请求对象DeleteIndexRequest request new DeleteIndexRequest(student);// 3.发送请求AcknowledgedResponse response client.indices().delete(request, RequestOptions.DEFAULT);// 4.操作响应结果System.out.println(response.isAcknowledged());// 5.关闭客户端client.close();}3 文档操作 新增修改文档 //新增修改文档Testpublic void addDocument() throws IOException {// 1.创建客户端对象连接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 2.创建请求对象IndexRequest request new IndexRequest(student).id(1);request.source(XContentFactory.jsonBuilder().startObject().field(id, 1).field(name, i love lxx).field(age, 20).endObject());// 3.发送请求IndexResponse response client.index(request, RequestOptions.DEFAULT);// 4.操作响应结果System.out.println(response.status());// 5.关闭客户端client.close();}根据id查询文档 // 根据id查询文档Testpublic void findByIdDocument() throws IOException {// 1.创建客户端对象连接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 2.创建请求对象GetRequest request new GetRequest(student, 1);// 3.发送请求GetResponse response client.get(request, RequestOptions.DEFAULT);// 4.操作响应结果System.out.println(response.getSourceAsString());// 5.关闭客户端client.close();}删除文档 // 删除文档Testpublic void DeleteDocument() throwsIOException {// 1.创建客户端对象连接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 2.创建请求对象DeleteRequest request new DeleteRequest(student, 1);// 3.发送请求DeleteResponse response client.delete(request, RequestOptions.DEFAULT);// 4.操作响应结果System.out.println(response.status());// 5.关闭客户端client.close();}3 搜索操作 搜索所有文档 //搜索所有文档Testpublic void queryAllDocument() throws IOException {// 1.创建客户端对象连接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 创建搜索条件SearchSourceBuilder searchSourceBuilder new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchAllQuery());// 创建请求对象SearchRequest request new SearchRequest(student).source(searchSourceBuilder);// 发送请求SearchResponse response client.search(request, RequestOptions.DEFAULT);// 输出返回结果for (SearchHit hit : response.getHits()) {System.out.println(hit.getSourceAsString());}// 关闭客户端client.close();} 根据关键词搜索文档 //根据关键词搜索文档Testpublic void queryTermDocument() throwsIOException {// 创建客户端对象链接ESRestHighLevelClient client newRestHighLevelClient(RestClient.builder(newHttpHost(192.168.66.113, 9200, http)));// 创建请求条件SearchSourceBuilder searchSourceBuilder new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.termQuery(name, lxx));// 创建请求对象SearchRequest request new SearchRequest(student).source(searchSourceBuilder);// 发送请求SearchResponse response client.search(request, RequestOptions.DEFAULT);// 输出返回结果for (SearchHit hit : response.getHits()) {System.out.println(hit.getSourceAsString());}// 关闭客户端client.close();}七 SpringDataES 1 入门案例 项目搭建 Spring Data ElasticSearch是Spring对原生JAVA操作Elasticsearch 封装之后的产物。它通过对原生API的封装使得JAVA程序员可以简单的对Elasticsearch进行操作。 创建SpringBoot项目加入Spring Data Elasticsearch起步依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-elasticsearch/artifactId/dependency编写配置文件 spring:elasticsearch:uris: http://192.168.66.113:9200此时Spring Data ElasticSearch项目已经搭建完成。 创建实体类 一个实体类的所有对象都会存入ES的一个索引中所以我们在创建实体类时关联ES索引 Data NoArgsConstructor AllArgsConstructor Document(indexName product, createIndex true) public class Product {IdField(type FieldType.Integer, store true, index true)private Integer id;Field(type FieldType.Text, store true, index true,analyzer ik_max_word, searchAnalyzer ik_max_word)private String productName;Field(type FieldType.Text, store true, index true,analyzer ik_max_word, searchAnalyzer ik_max_word)private String productDesc;}Document标记在类上标记实体类为文档对象一般有如下属性 indexName对应索引的名称 createIndex是否自动创建索引 Id标记在成员变量上标记一个字段为主键该字段的值会同步到ES该文档的id值。 Field标记在成员变量上标记为文档中的域一般有如下属性 type域的类型 index是否创建索引默认是 true store是否单独存储默认是 false analyzer分词器 searchAnalyzer搜索时的分词器 创建Repository接口 创建Repository接口继承ElasticsearchRepository该接口提供了文档的增删改查方法 public interface ProductRepository extends ElasticsearchRepositoryProduct, Integer { }测试方法 编写测试类注入Repository接口并测试Repository接口的增删改 查方法 SpringBootTest public class ProductRepositoryTest {Autowiredprivate ProductRepository repository;Testpublic void addDocument() {Product product new Product(1, iphone30, iphone30是苹果最新手机);repository.save(product);}Testpublic void updateDocument() {Product product new Product(1, iphone31, iphone31是苹果最新手机);repository.save(product);}Testpublic void findAllDocument() {IterableProduct all repository.findAll();for (Product product : all) {System.out.println(product);}}Testpublic void findDocumentById() {OptionalProduct product repository.findById(1);System.out.println(product.get());} }2 查询方式 接下来我们讲解SpringDataES支持的查询方式首先准备一些文档数据 // 添加一些数据repository.save(new Product(2, 三体1, 三体1 是优秀的科幻小说));repository.save(new Product(3, 三体2, 三体2 是优秀的科幻小说));repository.save(new Product(4, 三体3, 三体3 是优秀的科幻小说));repository.save(new Product(5, elasticsearch, elasticsearch是基于lucene开发的优秀的搜索引擎));使用Repository继承的方法查询文档 该方式我们之前已经讲解过了 使用DSL语句查询文档 ES通过json类型的请求体查询文档方法如下 GET /索引/_search {query:{搜索方式:搜索参数} }query后的json对象称为DSL语句我们可以在接口方法上使用 Query注解自定义DSL语句查询 Query({\n \match\: {\n \productDesc\: \?0\\n }\n })ListProduct findByProductDescMatch(String keyword);Query({\n \match\: {\n \productDesc\: {\n \query\: \?0\,\n \fuzziness\: 1\n }\n }\n })ListProduct findByProductDescFuzzy(String keyword);按照规则命名方法进行查询 只需在Repository接口中按照SpringDataES的规则命名方法该方法就能完成相应的查询。规则查询方法以findBy开头涉及查询条件时条件的属性用条件关键字连接。 关键字命名规则解释示例andfindByField1AndField2根据Field1和Field2 获得数据findByTitleAndContentorfindByField1OrField2 根据Field1或Field2 获得数据findByTitleOrContentisfindByField根据Field获得数据findByTitlenotfindByFieldNot根据Field获得补集数据findByTitleNotbetweenfindByFieldBetween获得指定范围的数据findByPriceBetween ListProduct findByProductName(String productName);ListProduct findByProductNameOrProductDesc(String productName, String productDesc);ListProduct findByIdBetween(Integer startId, Integer endId);3 分页查询 使用继承或自定义的方法时在方法中添加Pageable类型的参数 返回值为Page类型即可进行分页查询。 // 测试继承的方法Testpublic void testFindPage() {// 参数1页数参数2每页条数Pageable pageable PageRequest.of(1, 3);PageProduct page repository.findAll(pageable);System.out.println(总条数 page.getTotalElements());System.out.println(总页数 page.getTotalPages());System.out.println(数据 page.getContent());}// 自定义方法PageProduct findByProductDesc(String productDesc, Pageable pageable);// 测试自定义方法Testpublic void testFindPage2() {Pageable pageable PageRequest.of(0, 2);PageProduct page repository.findByProductDesc(三体, pageable);System.out.println(总条数 page.getTotalElements());System.out.println(总页数 page.getTotalPages());System.out.println(数据 page.getContent());}4 结果排序 使用继承或自定义的方法时在方法中添加Sort类型的参数即可进行结果排序。 // 结果排序Testpublic void testFindSort() {Sort sort Sort.by(Sort.Direction.DESC, id);IterableProduct all repository.findAll(sort);for (Product product : all) {System.out.println(product);}}// 测试分页加排序Testpublic void testFindPage3() {Sort sort Sort.by(Sort.Direction.DESC, id);Pageable pageable PageRequest.of(0, 2, sort);PageProduct page repository.findByProductDesc(三体, pageable);System.out.println(总条数 page.getTotalElements());System.out.println(总页数 page.getTotalPages());System.out.println(数据 page.getContent());}5 template工具类 SpringDataElasticsearch提供了一个工具类 ElasticsearchRestTemplate我们使用该类对象也能对ES进行操作。 操作索引 Autowiredprivate ElasticsearchRestTemplate template;// 新增索引Testpublic void addIndex() {// 获得索引操作对象IndexOperations indexOperations template.indexOps(Product.class);// 创建索引,注该方法无法设置索引结构不推荐使用indexOperations.create();}// 删除索引Testpublic void delIndex() {// 获得索引操作对象IndexOperations indexOperations template.indexOps(Product.class);// 删除索引indexOperations.delete();}增删改文档 template操作文档的常用方法 save()新增/修改文档delete()删除文档 // 新增/修改文档Testpublic void addDocument() {Product product new Product(7, es1, es是一款优秀的搜索引擎);template.save(product);}// 删除文档Testpublic void delDocument() {template.delete(7, Product.class);}查询文档 template的search方法可以查询文档 SearchHitsT search(Query query, ClassT clazz)查询文档query是查询条件对象clazz是结果 类型。用法如下 // 查询文档Testpublic void searchDocument() {// 1.确定查询方式// MatchAllQueryBuilder builder QueryBuilders.matchAllQuery();// TermQueryBuilder builder QueryBuilders.termQuery(productDesc, 手机);MatchQueryBuilder builder QueryBuilders.matchQuery(productDesc, 我喜欢看科幻小说);// 2.构建查询条件NativeSearchQuery query newNativeSearchQueryBuilder().withQuery(builder).build();// 3.查询SearchHitsProduct result template.search(query, Product.class);// 4.处理查询结果for (SearchHitProduct productSearchHit : result) {Product product productSearchHit.getContent();System.out.println(product);}}复杂条件查询 Testpublic void searchDocument2() { // String productName 三体; // String productDesc 小说;String productName null;String productDesc null;// 1.确定查询方式BoolQueryBuilder builder QueryBuilders.boolQuery();// 如果没有传入参数查询所有if (productName null productDesc null) {MatchAllQueryBuilder matchAllQueryBuilder QueryBuilders.matchAllQuery();builder.must(matchAllQueryBuilder);} else {if (productName ! null productName.length() 0) {MatchQueryBuilder queryBuilder1 QueryBuilders.matchQuery(productName, productName);builder.must(queryBuilder1);}if (productDesc ! null productDesc.length() 0) {MatchQueryBuilder queryBuilder2 QueryBuilders.matchQuery(productDesc, productDesc);builder.must(queryBuilder2);}}// 2.构建查询条件NativeSearchQuery query new NativeSearchQueryBuilder().withQuery(builder).build();// 3.查询SearchHitsProduct result template.search(query, Product.class);// 4.处理查询结果for (SearchHitProduct productSearchHit : result) {Product product productSearchHit.getContent();System.out.println(product);}} 分页查询 // 分页查询文档Testpublic void searchDocumentPage() {// 1.确定查询方式MatchAllQueryBuilder builder QueryBuilders.matchAllQuery();// 2.构建查询条件// 分页条件Pageable pageable PageRequest.of(0, 3);NativeSearchQuery query new NativeSearchQueryBuilder().withQuery(builder).withPageable(pageable).build();// 3.查询SearchHitsProduct result template.search(query, Product.class);// 4.将查询结果封装为Page对象ListProduct content new ArrayList();for (SearchHitProduct productSearchHit : result) {Product product productSearchHit.getContent();content.add(product);}/*** 封装Page对象参数1具体数据参数2分页条件对象参数3总条数*/PageProduct page new PageImpl(content, pageable, result.getTotalHits());System.out.println(page.getTotalElements());System.out.println(page.getTotalPages());System.out.println(page.getContent());}结果排序 Testpublic void searchDocumentSort() {// 1.确定查询方式MatchAllQueryBuilder builder QueryBuilders.matchAllQuery();// 2.构建查询条件// 排序条件SortBuilder sortBuilder SortBuilders.fieldSort(id).order(SortOrder.DESC);NativeSearchQuery query new NativeSearchQueryBuilder().withQuery(builder).withSorts(sortBuilder).build();// 3.查询SearchHitsProduct result template.search(query, Product.class);// 4.处理查询结果for (SearchHitProduct productSearchHit : result) {Product product productSearchHit.getContent();System.out.println(product);}} 八 Elasticsearch集群 1 概念 在单台ES服务器上随着一个索引内数据的增多会产生存储、效率、安全等问题。 假设项目中有一个500G大小的索引但我们只有几台200G硬盘的服务器此时是不可能将索引放入其中某一台服务器中的。 此时我们需要将索引拆分成多份分别放入不同的服务器中此时这几台服务器维护了同一个索引我们称这几台服务器为一个集群其中的每一台服务器为一个节点每一台服务器中的数据称为一个分片。 此时如果某个节点故障则会造成集群崩溃所以每个节点的分片往往还会创建副本存放在其他节点中此时一个节点的崩溃就不会影响整个集群的正常运行。 节点node一个节点是集群中的一台服务器是集群的一部分。它存储数据参与集群的索引和搜索功能。集群中有一个为主节点主节点通过ES内部选举产生。 集群cluster一组节点组织在一起称为一个集群它们共同持有整个的数据并一起提供索引和搜索功能。 分片shardsES可以把完整的索引分成多个分片分别存储在不同的节点上。 副本replicasES可以为每个分片创建副本提高查询效率 保证在分片数据丢失后的恢复。 注 分片的数量只能在索引创建时指定索引创建后不能再更改分片数量但可以改变副本的数量。 为保证节点发生故障后集群的正常运行ES不会将某个分片和它的副本存在同一台节点上。 2 搭建集群 安装第一个ES节点 安装 #解压 tar -zxvf elasticsearch-7.17.0-linux-x86_64.tar.gz#重命名 mv elasticsearch-7.17.0 myes1#移动文件夹 mv myes1 /usr/local/#安装ik分词器 unzip elasticsearch-analysis-ik-7.17.0.zip -d /usr/local/myes1/plugins/analysis-ik#安装拼音分词器 unzip elasticsearch-analysis-pinyin-7.17.0.zip -d /usr/local/myes1/plugins/analysis-pinyin#es用户取得该文件夹权限 chown -R es:es /usr/local/myes1修改配置文件 #打开节点一配置文件 vim /usr/local/myes1/config/elasticsearch.yml配置如下信息 #集群名称保证唯一 cluster.name: my_elasticsearch #节点名称必须不一样 node.name: node1 #可以访问该节点的ip地址 network.host: 0.0.0.0 #该节点服务端口号 http.port: 9200 #集群间通信端口号 transport.tcp.port: 9300 #候选主节点的设备地址 discovery.seed_hosts: [127.0.0.1:9300,127.0.0.1:9301,127.0.0.1:9302] #候选主节点的节点名 cluster.initial_master_nodes: [node1,node2,node3]启动 #切换为es用户 su es #后台启动第一个节点 ES_JAVA_OPTS-Xms512m -Xmx512m /usr/local/myes1/bin/elasticsearch -d安装第二个ES节点 安装 #解压 tar -zxvf elasticsearch-7.17.0-linux-x86_64.tar.gz#重命名 mv elasticsearch-7.17.0 myes2#移动文件夹 mv myes2 /usr/local/#安装ik分词器 unzip elasticsearch-analysis-ik-7.17.0.zip -d /usr/local/myes2/plugins/analysis-ik#安装拼音分词器 unzip elasticsearch-analysis-pinyin-7.17.0.zip -d /usr/local/myes2/plugins/analysis-pinyin#es用户取得该文件夹权限 chown -R es:es /usr/local/myes2修改配置文件 #打开节点二配置文件 vim /usr/local/myes2/config/elasticsearch.yml配置如下信息 #集群名称保证唯一 cluster.name: my_elasticsearch #节点名称必须不一样 node.name: node2 #可以访问该节点的ip地址 network.host: 0.0.0.0 #该节点服务端口号 http.port: 9201 #集群间通信端口号 transport.tcp.port: 9301 #候选主节点的设备地址 discovery.seed_hosts: [127.0.0.1:9300,127.0.0.1:9301,127.0.0.1:9302] #候选主节点的节点名 cluster.initial_master_nodes: [node1,node2,node3]启动 #切换为es用户 su es#后台启动第二个节点 ES_JAVA_OPTS-Xms512m -Xmx512m /usr/local/myes2/bin/elasticsearch -d安装第三个ES节点 安装 #解压 tar -zxvf elasticsearch-7.17.0-linux-x86_64.tar.gz#重命名 mv elasticsearch-7.17.0 myes3#移动文件夹 mv myes3 /usr/local/#安装ik分词器 unzip elasticsearch-analysis-ik-7.17.0.zip -d /usr/local/myes3/plugins/analysis-ik#安装拼音分词器 unzip elasticsearch-analysis-pinyin-7.17.0.zip -d /usr/local/myes3/plugins/analysis-pinyin#es用户取得该文件夹权限 chown -R es:es /usr/local/myes3修改配置文件 #打开节点三配置文件 vim /usr/local/myes3/config/elasticsearch.yml配置如下信息 #集群名称保证唯一 cluster.name: my_elasticsearch #节点名称必须不一样 node.name: node3 #可以访问该节点的ip地址 network.host: 0.0.0.0 #该节点服务端口号 http.port: 9202 #集群间通信端口号 transport.tcp.port: 9302 #候选主节点的设备地址 discovery.seed_hosts: [127.0.0.1:9300,127.0.0.1:9301,127.0.0.1:9302] #候选主节点的节点名 cluster.initial_master_nodes: [node1,node2,node3]启动 #切换为es用户 su es#后台启动第三个节点 ES_JAVA_OPTS-Xms512m -Xmx512m /usr/local/myes3/bin/elasticsearch -d测试集群 访问 http://虚拟机IP:9200/_cat/nodes 查看是否集群搭建成功。 kibana连接es集群 在kibana中访问集群 # 打开kibana配置文件 vim /usr/local/kibana-7.17.0-linux-x86_64/config/kibana.yml添加如下配置 # 该集群的所有节点 elasticsearch.hosts: [http://虚拟机IP:9200,http://虚拟机IP:9201,http://虚拟机IP:9202]启动kibana #切换为es用户 su es#启动kibana /usr/local/kibana-7.17.0-linux-x86_64/bin/kibana访问kibana http://虚拟机IP:5601 3 测试集群状态 在集群中创建一个索引 PUT /product1 {settings: {number_of_shards: 5,// 分片数number_of_replicas: 1// 每个分片的副本数},mappings: {properties: {id: {type: integer,store: true,index: true},productName: {type: text,store: true,index: true},productDesc: {type: text,store: true,index: true}}} }查看集群状态 # 查看集群健康状态 GET /_cat/health?v# 查看索引状态 GET /_cat/indices?v# 查看分片状态 GET /_cat/shards?v4 故障应对水平扩容 关闭一个节点可以发现ES集群可以自动进行故障应对。重新打开该节点可以发现ES集群可以自动进行水平扩容。分片数不能改变但是可以改变每个分片的副本数 PUT /索引/_settings {number_of_replicas: 副本数 }九 Elasticsearch优化 1 磁盘选择 ES的优化即通过调整参数使得读写性能更快 磁盘通常是服务器的瓶颈。Elasticsearch重度使用磁盘磁盘的效 率越高Elasticsearch的执行效率就越高。这里有一些优化磁盘的技巧 使用SSD固态硬盘它比机械磁盘优秀多了。使用RAID0模式将连续的数据分散到多个硬盘存储这样可以并行进行IO操作,代价是一块硬盘发生故障就会引发系统故障。不要使用远程挂载的存储。 2 内存设置 ES默认占用内存是4GB我们可以修改config/jvm.option设置ES的 堆内存大小Xms表示堆内存的初始大小Xmx表示可分配的最大内存。 Xmx和Xms的大小设置为相同的可以减轻伸缩堆大小带来的压力。Xmx和Xms不要超过物理内存的50%因为ES内部的Lucene也要占据一部分物理内存。Xmx和Xms不要超过32GB由于Java语言的特性堆内存超过32G会浪费大量系统资源所以在内 存足够的情况下最终我们都会采用设置为31G -Xms 31g -Xmx 31g例如在一台128GB内存的机器中我们可以创建两个节点每个节点分配31GB内存。 3 分片策略 分片和副本数并不是越多越好。每个分片的底层都是一个Lucene索引会消耗一定的系统资源。且搜索请求需要命中索引中的所有分片分片数过多会降低搜索性能。索引的分片数需要架构师和技术人员对业务的增长有预先的判断一般来说我们遵循以下原则 每个分片占用的硬盘容量不超过ES的最大JVM的堆空间设置(一 般设置不超过32G。比如如果索引的总容量在500G左右 那分片数量在16个左右即可。分片数一般不超过节点数的3倍。比如如果集群内有10个节点则分片数不超过30个。推迟分片分配节点中断后集群会重新分配分片。但默认集群会等待一分钟来查看节点是否重新加入。我们可以设置等待的时长减少重新分配的次数 PUT /索引/_settings {settings:{index.unassianed.node_left.delayed_timeout:5m} }减少副本数量进行写入操作时需要把写入的数据都同步到副本副本越多写入的效率就越慢。我们进行大批量进行写入操作时可以先设置副本数为0写入完成后再修改回正常的状态。 十 Elasticsearch案例 1 需求说明 接下来我们使用ES模仿百度搜索即自动补全搜索引擎效果 2 ES自动补全 es为我们提供了关键词的自动补全功能 GET /索引/_search {suggest: {prefix_suggestion: {// 自定义推荐名prefix: elastic,// 被补全的关键字completion: {field: productName,// 查询的域skip_duplicates: true, //忽略重复结果size: 10 //最多查询到的结果数}}} }注自动补全对性能要求极高ES不是通过倒排索引来实现的所以需要将对应的查询字段类型设置为completion。 PUT /product2 {mappings: {properties: {id: {type: integer,store: true,index: true},productName: {type: completion},productDesc: {type: text,store: true,index: true}}} }POST /product2/_doc {id:1,productName:elasticsearch1,productDesc:elasticsearch1 is a good search engine } POST /product2/_doc {id:2,productName:elasticsearch2,productDesc:elasticsearch2 is a good search engine } POST /product2/_doc {id:3,productName:elasticsearch3,productDesc:elasticsearch3 is a good search engine }测试自动补全功能 GET /product2/_search {suggest: {prefix_suggestion: {prefix: elastic,completion: {field: productName,skip_duplicates: true,size: 10}}} }3 创建索引 PUT /news {settings: {analysis: {analyzer: {ik_pinyin: {tokenizer: ik_smart,filter: pinyin_filter},tag_pinyin: {tokenizer: keyword,filter: pinyin_filter}},filter: {pinyin_filter: {type: pinyin,keep_joined_full_pinyin: true,keep_original: true,remove_duplicated_term: true}}}},mappings: {properties: {id: {type: integer,index: true},title: {type: text,index: true,analyzer: ik_pinyin,search_analyzer: ik_smart},content: {type: text,index: true,analyzer: ik_pinyin,search_analyzer: ik_smart},url: {type: keyword,index: true},tags: {type: completion,analyzer: tag_pinyin,search_analyzer: tag_pinyin}}} }4 准备数据 将提前准备好的sql导入数据库 /* SQLyog Ultimate v12.09 (64 bit) MySQL - 5.5.40-log : Database - news ********************************************************************* *//*!40101 SET NAMES utf8 */;/*!40101 SET SQL_MODE*/;/*!40014 SET OLD_UNIQUE_CHECKSUNIQUE_CHECKS, UNIQUE_CHECKS0 */; /*!40014 SET OLD_FOREIGN_KEY_CHECKSFOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS0 */; /*!40101 SET OLD_SQL_MODESQL_MODE, SQL_MODENO_AUTO_VALUE_ON_ZERO */; /*!40111 SET OLD_SQL_NOTESSQL_NOTES, SQL_NOTES0 */; CREATE DATABASE /*!32312 IF NOT EXISTS*/news /*!40100 DEFAULT CHARACTER SET utf8 */;USE news;/*Table structure for table news */DROP TABLE IF EXISTS news;CREATE TABLE news (id int(11) NOT NULL AUTO_INCREMENT,title varchar(255) NOT NULL,url varchar(255) DEFAULT NULL,content text,tags varchar(1000) DEFAULT NULL,PRIMARY KEY (id) USING BTREE ) ENGINEInnoDB AUTO_INCREMENT92 DEFAULT CHARSETutf8 ROW_FORMATDYNAMIC;/*Data for the table news */insert into news(id,title,url,content,tags) values (1,略...,略...,略...,略...;/*!40101 SET SQL_MODEOLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKSOLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKSOLD_UNIQUE_CHECKS */; /*!40111 SET SQL_NOTESOLD_SQL_NOTES */; 使用logstash工具可以将mysql数据同步到es中 解压logstash-7.17.0-windows-x86_64.zip logstash要和elastisearch版本一致 在解压路径下的/config中创建mysql.conf文件文件写入以下脚本内容 input {jdbc {jdbc_driver_library F:\001-after-end\笔记\14-全文检索与日志管理\Elasticsearch\软件\案例\mysql-connector-java-5.1.37-bin.jarjdbc_driver_class com.mysql.jdbc.Driverjdbc_connection_string jdbc:mysql:///newsjdbc_user rootjdbc_password 123456schedule * * * * *jdbc_default_timezone Asia/Shanghaistatement SELECT * FROM news;} }filter {mutate {split {tags ,}} }output {elasticsearch {hosts [192.168.66.113:9200]index newsdocument_id %{id}} } 在解压路径下打开cmd黑窗口运行命令 bin\logstash -f config\mysql.conf注意: logstash解压路径不能有中文 mysql.conf的编码必须为utf-8; 配置es可以远程访问参照第六章配置。 测试自动补齐 GET /news/_search {suggest: {my_suggest: {prefix: li,completion: {field: tags,skip_duplicates: true,size: 10}}} }5 项目搭建 创建Springboot项目加入SpringDataElasticsearch和SpringMVC 的起步依赖 dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-elasticsearch/artifactId /dependencydependency groupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId /dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional /dependency 写配置文件 spring:elasticsearch:uris: 192.168.66.113:9200logging:pattern:console: %d{HH:mm:ss.SSS} %clr(%-5level) --- [%-15thread]%cyan(%-50logger{50}):%msg%n6 创建实体类 //索引已经提前创建好了下面的实体类则不用添加那些和创建索引有关的属性了 Document(indexName news) Data public class News {IdFieldprivate Integer id;Fieldprivate String title;Fieldprivate String content;Fieldprivate String url;CompletionFieldTransientprivate Completion tags; } 7 创建Repository接口 public interface NewsRepository extends ElasticsearchRepositoryNews, Integer { }8 自动补全功能 Service public class NewsService {Autowiredprivate ElasticsearchRestTemplate template;// 自动补齐public ListString autoSuggest(String keyword) {// 1.创建补全请求SuggestBuilder suggestBuilder new SuggestBuilder();// 2.构建补全条件SuggestionBuilder suggestionBuilder SuggestBuilders.completionSuggestion(tags).prefix(keyword).skipDuplicates(true).size(10);suggestBuilder.addSuggestion(prefix_suggestion, suggestionBuilder);// 3.发送请求SearchResponse response template.suggest(suggestBuilder, IndexCoordinates.of(news));// 4.处理结果ListString result response.getSuggest().getSuggestion(prefix_suggestion).getEntries().get(0).getOptions().stream().map(Suggest.Suggestion.Entry.Option::getText).map(Text::toString).collect(Collectors.toList());return result;} } 对应的原生es搜索为 GET /news/_search {suggest: {prefix_suggestion: {prefix: li,completion: {field: tags,skip_duplicates: true,size: 10}}} }结果为 {took : 33,timed_out : false,_shards : {total : 1,successful : 1,skipped : 0,failed : 0},hits : {total : {value : 0,relation : eq},max_score : null,hits : [ ]},suggest : {prefix_suggestion : [{text : li,offset : 0,length : 2,options : [{text : 利哈伊谷,_index : news,_type : _doc,_id : 18,_score : 1.0,_source : {timestamp : 2023-05-06T08:39:01.668Z,tags : [美国,美国黑五,利哈伊谷,购物中心,视频,脸书,保安,塞缪尔·萨法迪,海军陆战队,现役海军陆战队员,退役海军陆战队员,礼品店,礼品,打斗,安全人员,安全],content : 海外网12月1日电 近日一年一度的“黑色星期五”购物节拉开帷幕热情的购物者涌向百货商店都希望能买到打折商品。然而美国各地也因此发生了几起暴力事件。美媒甚至感慨“如果一年有一天会失去对人性的希望那就是‘黑五’。”福克斯新闻网报道了本周内美国各个州因“黑五”引发的冲突事件目击者拍下视频画面在社交平台上疯传。当地时间11月29日晚上在宾夕法尼亚州利哈伊谷购物中心的Forever 21商店外发生了一场打斗事件。有网友将视频拍摄下来略......,id : 18,url : https://news.sina.com.cn/w/2019-12-01/doc-iihnzhfz2885717.shtml,title : 美国黑五冲突不断多地发生斗殴 有人鼻子被打断,version : 1}},.......略]}]} } 9 搜索关键字功能 在repository接口中添加高亮搜索关键字方法 // 高亮搜索关键字 Highlight(fields {HighlightField(name title), HighlightField(name content)}) ListSearchHitNews findByTitleMatchesOrContentMatches(String title, String content);service类中调用该方法 AutowiredNewsRepository repository;// 查询关键字public ListNews highLightSearch(String keyword) {ListSearchHitNews result repository.findByTitleMatchesOrContentMatches(keyword, keyword);// 处理结果封装为News类型的集合ListNews newsList new ArrayList();for (SearchHitNews newsSearchHit : result) {News news newsSearchHit.getContent();// 高亮字段MapString, ListString highlightFields newsSearchHit.getHighlightFields();if (highlightFields.get(title) ! null) {news.setTitle(highlightFields.get(title).get(0));}if (highlightFields.get(content) ! null) {news.setContent(highlightFields.get(content).get(0));}newsList.add(news);}return newsList;}对应的原生es搜索为 GET /news/_search {query: {bool: {should: [{match: {title: 江西}},{match: {content: 江西}}]}},highlight: {fields: [{content: {fragment_size: 20,number_of_fragments: 5}},{title: {fragment_size: 20,number_of_fragments: 5}}],pre_tags: [em],post_tags: [/em]} }结果为 {took : 15,timed_out : false,_shards : {total : 1,successful : 1,skipped : 0,failed : 0},hits : {total : {value : 2,relation : eq},max_score : 11.891368,hits : [{_index : news,_type : _doc,_id : 91,_score : 11.891368,_source : {timestamp : 2023-05-06T08:39:01.686Z,tags : [江西九江,江西,九江,吴城,吴城水上公路,老鼠,江西暴雨,暴雨,鄱阳湖,洪水,长江,三峡],content : 7月4日江西九江吴城水上公路因暴雨被洪水淹没有一辆车在水中熄火动弹不了一市民和她老公去现场救援时发现公路旁有个亭子发现里面竟有七八十只老鼠在亭内躲避洪水并表示第一次看到这么多老鼠。该市民称每年雨季这条公路都会被淹没在此呼吁广大市民雨季行车注意安全。江西省继续发布洪水预警鄱阳湖防洪对长江流域相当重要今日10时江西省继续发布洪水红色预警鄱阳湖水位超警戒3.60米形势严峻。鄱阳湖是江西的“集水盆”江西境内五大河流经略......,id : 91,url : https://baijiahao.baidu.com/s?id1672108752181366032wfrspiderforpc,title : 江西暴雨近百只老鼠凉亭内躲洪水密密麻麻紧贴石墩江西暴雨近百只老鼠凉亭内躲洪水密密麻麻紧贴石墩,version : 1},highlight : {title : [em江西/em暴雨近百只老鼠凉亭内躲洪水密密麻麻紧贴石墩,em江西/em暴雨近百只老鼠凉亭内躲洪水密密麻麻紧贴石墩],content : [7月4日em江西/em九江吴城水上公路因暴雨被洪水淹没,鄱阳湖是em江西/em的“集水盆”em江西/em境内五大河流经鄱阳湖集纳后进入长江]}},略......]} } 10 创建Controller类 RestController public class NewsController {Autowiredprivate NewsService newsService;GetMapping(/autoSuggest)public ListString autoSuggest(String term) { // 前端使用jqueryUI发送的参数默认名为termreturn newsService.autoSuggest(term);}GetMapping(/highLightSearch)public ListNews highLightSearch(String term) {return newsService.highLightSearch(term);} }11 前端页面 我们使用jqueryUI中的autocomplete插件完成项目的前端实现 略。。。
http://www.dnsts.com.cn/news/163432.html

相关文章:

  • 网站交换链接的常见形式宁波优化网站哪家好
  • 做电缆好的网站陕西seo快速排名
  • 桂林企业网站建设网络规划设计师 第二版 教材
  • 郑州做网站价格app快速开发平台
  • 卡二卡四无卡国产网站网络营销的职能
  • 网站开发人才需求网页设计与网站架设
  • 为什么手机进网站乱码网站怎么做优化推广
  • 长沙手机网站建设公司排名网站的建设时间怎么查
  • 长沙建网站设计公司营销型集团网站
  • 山西建设网官方网站佛山外贸网站设计
  • 网站会对特殊的ip做跳转设计外贸网站建设
  • 网站建设网络课程洛阳信息港洛阳城事
  • 深圳商务网站建设成都哪里好玩
  • 中国建设工程招投网站网络设计课
  • 宗亲网站开发6永久免费国外域名注册
  • 保定专业网站建设开发公司怎么做qq网站
  • 潍坊做企业手机版网站区块链的网站怎么做
  • 专业的英文网站建设开网络公司
  • 搜索引擎是软件还是网站求个国外在线网站
  • 网站建设使用情况免费发布信息平台网
  • 网页设计登录界面模板优化大师优化项目有
  • 电商网站可以用dw做手机网站 程序
  • iis怎么添加网站营销策划公司加盟
  • icp备案网站名称郑州市
  • 如何识别网站的建站程序离我最近的物流公司
  • 做企业网站推广多少钱什么网站可以在线做考教师岗位的题
  • 郑州中心站怎样制作网页设计
  • 深圳营销型网站公司微信公众号影视网站怎么做
  • 朝阳做网站微信视频制作小程序
  • 微网站制作电话免费制作个人简历的网站