solr-es
一、lucene
1.是什么
是apache提供的一套java写的用于全文检索工具包,该工具包提供了用于实现全文检索的api类,可用于实现搜索引擎功能.
2.搜索常用方法
-
顺序扫描法:应用于数据结构固定且数据量不大
-
全文检索:应用于数据结构不固定,且数据量大,比如百度,淘宝。。。
- 原理:将非结构化数据中的一部分信息提取出来,重新组织,使其变 的有一定结构,然后对此 数据进行搜索,从而提高效率.
- 倒排索引:我们把这部分从非结构化数据中提取出然后重新组织的信息,叫索引表,该索引表中的每一项都包含一个分词和包含该词的文章的地址。由于不是由文章来确定其分词值,而是由分词来确定文章的位置,因而称为倒排索引
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wGawWlom-1635673101258)(picture\solr搜索原理.png)]
二、solr
##1.安装
###a. 下载地址:
http://archive.apache.org/dist/lucene/solr
###b.解压启动
- 解压 tar -zxvf solr-7.7.2_linux.tgz -C /opt/module/
bin/solr start -force—force作用是可用root用户启动而不告警
./solr restart -force
windows: bin/solr.cmd start
bin/solr stop----关闭
bin/solr restart----重启
如果不希望看到告警,可修改配置文件
-
vim bin/solr.in.sh
SOLR_ULIMIT_CHECKS=false
-
vim /etc/security/limits.conf文件尾部添加下面两行
* hard nofile 65000 * soft nofile 65000
###c.测试
在window浏览器中输入http://192.168.188.100:8983/solr
##2. solr core
一个solr core是包含索引和配置文件和数据的运行实例,多个solr实例就是solr collection
如何创建solr core
linux:
bin/solr create -c first -force----在server/solr目录中创建first文件夹
windows:
solr.cmd -c first
##3. 中文分词器
###a.拷贝分词器
cp /opt/module/solr-7.7.2/contrib/analysis-extras/lucene-libs/lucene-analyzers-smartcn-7.7.2.jar /opt/module/solr-7.7.2/server/solr-webapp/webapp/WEB-INF/lib/
###b.修改core的配置
vim /opt/module/solr-7.7.2/server/solr/first/conf/managed-schema
添加
<fieldType name="text_hmm_chinese" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="org.apache.lucene.analysis.cn.smart.HMMChineseTokenizerFactory"/> </analyzer> </fieldType>
###c. 重启solr服务
#三、ElasticSearch
1.es介绍
是一个使用java,且基于lucene技术开发的搜索引擎框架,提供了一个统一的基于restful风格的api接口
2. es与solr区别(了解)
1.ElasticSearch新, 注重于核心功能,高级功能多有第三方插件提供;Solr已经存在了更长的时间,更稳定,功能多
2.Solr支持更多格式的数据,比如JSON、XML、CSV,而Elasticsearch仅支持json文件格式。
3.Solr 利用 Zookeeper 进行分布式管理,而 Elasticsearch 自身带有分布式协调管理功能。Elasticsearch专为云设计,是分布式首选。
4.当单纯的对已有数据进行搜索时,Solr更快。当实时建立索引时, Solr会产生io阻塞,查询性能较差, Elasticsearch具有明显的优势。随着数据量的增加,Solr的搜索效率会变得更低,而Elasticsearch却没有明显的变化。
3.安装
官网下载:
https://www.elastic.co/products/elasticsearch https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.12.1-linux-x86_64.tar.gz 解压
tar -zxvf /opt/software/java/elasticsearch-7.12.1-linux-x86_64.tar.gz -C /opt/module/ 修改jdk
运行该版本运行需要jdk11,需要把关于jdk的三个环境变量注释掉
vim /etc/profile
#JAVA_HOME=/opt/module/jdk1.8.0_144 #CLASSPATH=.:$JAVA_HOME/lib/tools.jar #PATH=$JAVA_HOME/bin:$PATH #export JAVA_HOME CLASSPATH PATH es默认只允许本机才能访问,解决如下:
修改配置文件vim /opt/module/elasticsearch-7.12.1/config/elasticsearch.yml 在文件尾部添加下面几行配置
network.host: 0.0.0.0 http.port: 9200 cluster.initial_master_nodes: ["node-1"] node.name: node-1 bootstrap.system_call_filter: false #centos6内核版本为2.6。而Elasticsearch的插件要求至少3.5以上版本,禁用这个插件 打开文件数量
vim /etc/security/limits.conf 添加下面几行配置
es soft nofile 65535 es hard nofile 65535 es soft nproc 4096 es hard nproc 4096 虚拟内存修改
vim /etc/sysctl.conf ,添加下面这个配置
#限制一个进程可以拥有虚拟内存的大小 vm.max_map_count=262144 使上面的修改立刻生效:
sysctl -p
在es5之后都不能使用root帐户运行,要创建帐户
adduser es passwd es 两次输入密码 chown -R es /opt/module/elasticsearch-7.12.1/ 修改es文件夹拥有者为es用户 su es //切换到es用户 在es安装目录 cd /opt/module/elasticsearch-7.12.1 中运行下面命令 bin/elasticsearch //启动elasticsearch 测试: 192.168.188.100:9200/
##4.postMan下使用es
-
postman下载安装
https://www.postman.com/downloads/ -
维护索引
创建索引:postman中发送put请求,这里必须使用put http://192.168.188.100:9200/first 查询索引:get请求获取上面创建的信息 http://192.168.188.100:9200/first 查询所有索引:get获取全部信息 http://192.168.188.100:9200/_cat/indices?v delete请求删除 http://192.168.188.100:9200/first -
创建文档
-
post请求192.168.188.100:9200/first/_doc/1 ,最后的1表示id为1,如果没有则会产生默认的id值
-
在发送请求时,向请求体body中封装json数据:
body–>raw–>把文本格式从text修改为json,文本框中输入下面内容
{ "name":"孙子兵法", "price":"34", "info":"兵者,国之大事,死生之地,存亡之道,不可不察也", "author":"孙武" } -
-
查看文档
发送get请求,body中选择none,因为get请求不支持body中添加数据
192.168.188.100:9200/first/_doc/1 查询指定文档 192.168.188.100:9200/user/_search 查询所有 -
修改文档
-
整体更新:给出文档所有字段的数据,对所有字段都更新用put
-
put请求 192.168.188.100:9200/first/_doc/1
-
body–>raw–>json,文本框中添加要修改的内容
-
{ "name":"三十六计", "price":"111", "info":"瞒天过海,暗度陈仓,偷天换日", "author":"孙膑" } -
执行成功后,看到"result": “updated”
-
-
局部文档更新:只对文档中的部分字段更新。用post
-
post请求 192.168.188.100:9200/first/_update/1 ,注意,把doc换成update
-
body–>raw–>json,文本框中添加要修改的内容,注意json格式找成{doc:{}}
-
{ "doc":{ "name":"36鸡" } }
-
-
-
删除文档
delete请求192.168.188.100:9200/first/_doc/1
5. Java访问ES
----不掌握,了解
###1. 索引操作
-
pom依赖
<dependencies> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.8.0</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.9</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.11.0</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> </dependency> </dependencies> -
resources目录下log4j2.xml
<?xml version="1.0" encoding="UTF-8"?> <configuration> <appenders> <!--这个输出控制台的配置--> <console name="Console" target="SYSTEM_OUT"> <!--输出日志的格式--> <PatternLayout pattern="%d{YYYY-MM-dd HH:mm:ss} [%t] %-5p %c{1}:%L - %msg%n"/> </console> </appenders> <loggers> <root level="info"><!--all会显示所有信息--> <appender-ref ref="Console"/> </root> </loggers> </configuration> -
测试代码
public class EsIndex { RestHighLevelClient cli; @Before public void init() { cli=new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.188.100",9200,"http")) ); } @After public void end()throws Exception{ cli.close(); } @Test//创建索引 public void createIndex()throws Exception{ //创建索引请求 CreateIndexRequest req=new CreateIndexRequest("user"); //创建索引 CreateIndexResponse resp = cli.indices().create(req, RequestOptions.DEFAULT); //响应状态 boolean ack = resp.isAcknowledged(); System.out.println("索引操作状态:"+ack); } @Test public void searchIndex()throws Exception{ GetIndexRequest req = new GetIndexRequest("user"); //创建索引 GetIndexResponse resp = cli.indices().get(req, RequestOptions.DEFAULT); //响应状态 System.out.println(resp.getAliases()); System.out.println(resp.getSettings()); } @Test public void deleteIndex()throws Exception{ DeleteIndexRequest req =new DeleteIndexRequest("user"); AcknowledgedResponse resp = cli.indices().delete(req, RequestOptions.DEFAULT); System.out.println(resp.isAcknowledged()); } }
2. 文档操作
public class EsDoc { RestHighLevelClient cli; @Before public void init() { cli=new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.188.100",9200,"http")) ); } @After public void end()throws Exception{ cli.close(); } @Test public void insertData()throws Exception{ IndexRequest req=new IndexRequest().index("user").id("1"); User u=new User(); u.setName("this is test name"); u.setAge(120); String json = JSON.toJSONString(u); req.source(json, XContentType.JSON); IndexResponse resp = cli.index(req, RequestOptions.DEFAULT); System.out.println(resp.getResult()); } @Test public void updateData()throws Exception{ UpdateRequest req=new UpdateRequest().index("user").id("1"); req.doc(XContentType.JSON,"name","hello,it is test"); UpdateResponse resp = cli.update(req, RequestOptions.DEFAULT); System.out.println(resp.getResult()); } @Test public void queryData()throws Exception{ GetRequest req = new GetRequest().index("user").id("2"); GetResponse resp = cli.get(req, RequestOptions.DEFAULT); System.out.println(resp.getSourceAsString()); } @Test public void deleteData()throws Exception{ DeleteRequest req=new DeleteRequest().index("user").id("2"); DeleteResponse resp = cli.delete(req, RequestOptions.DEFAULT); System.out.println(resp.toString()); } @Test public void batchInsertData()throws Exception{ //产生批处理数据 BulkRequest batchReq=new BulkRequest(); batchReq.add(new IndexRequest().index("user").id("2").source(XContentType.JSON,"age",33,"name","a3")); batchReq.add(new IndexRequest().index("user").id("3").source(XContentType.JSON,"age",34,"name","a4")); batchReq.add(new IndexRequest().index("user").id("4").source(XContentType.JSON,"age",35,"name","a5")); batchReq.add(new IndexRequest().index("user").id("5").source(XContentType.JSON,"age",36,"name","a6")); //向客户端添加数据并请求写入 BulkResponse resp = cli.bulk(batchReq, RequestOptions.DEFAULT); } } @Data class User{ String name; int age; }
3. 高级查询
public class Search { RestHighLevelClient cli; SearchRequest req; SearchSourceBuilder sb; @Before public void init() { cli=new RestHighLevelClient( RestClient.builder(new HttpHost("192.168.188.100",9200,"http")) ); req = new SearchRequest().indices("user"); sb=new SearchSourceBuilder(); } @After public void end()throws Exception{ req.source(sb); //开始查询 SearchResponse resp = cli.search(req, RequestOptions.DEFAULT); //获取查询结果 SearchHits hits = resp.getHits(); System.out.println("一共查询到的数量:"+hits.getTotalHits()); hits.forEach(h->{ System.out.println(h.getSourceAsString()); //高亮显示时使用 //Text[]arr=h.getHighlightFields().get("name").fragments(); //System.out.println(arr[0].string()); }); cli.close(); } @Test//1.查询所有 public void searchAll(){ sb.query(QueryBuilders.matchAllQuery()); } @Test//2.根据条件查询 public void searchByCondition(){ sb.query(QueryBuilders.termQuery("name","a5")); } @Test//3.分页查询 public void searchByPage(){ int pageNo=1,pageSize=2; sb.from((pageNo-1)*pageSize).size(pageSize); } @Test//4.对结果排序查询 public void searchByOrder(){ sb.sort("age", SortOrder.DESC); } @Test//5.过滤显示的字段:参数1表示要显示什么字段,如果要显示的字段多,可用参数2表示不显示哪些字段 public void searchByField() throws Exception{ sb.fetchSource(new String[]{"name"},null); } @Test//6.多条件查询:must/mustNot逻辑与,should逻辑或 public void searchByMultiCondition() throws Exception{ BoolQueryBuilder bq= QueryBuilders.boolQuery(); bq.must(QueryBuilders.matchQuery("name","a3")).mustNot(QueryBuilders.matchQuery("age",23)); // bq.should(QueryBuilders.matchQuery("name","a3")).should(QueryBuilders.matchQuery("age",34)); sb.query(bq); } @Test//7.范围查找:greater than equal public void searchByRange() throws Exception{ RangeQueryBuilder rq=QueryBuilders.rangeQuery("age").gte(30).lte(35); sb.query(rq); } @Test//8.模糊查找 public void searchByLike() throws Exception{ //fuzziness:按给定的关键字a1查询,允许有一个字符的偏差,能查出a1,a2,a3...。 sb.query(QueryBuilders.fuzzyQuery("name","a1").fuzziness(Fuzziness.ONE)); } @Test//9.高亮查询 public void searchWithHighLight() throws Exception{ HighlightBuilder hb=new HighlightBuilder().preTags("<font color='red'>").postTags("</font>").field("name"); //通配符查询 QueryBuilder tb=QueryBuilders.wildcardQuery("name", "*"); sb.highlighter(hb).query(tb); } }
6. boot整合
使用springData操作es
###1. pom
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.3</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.4.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.41</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>2.4.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> </dependencies>
2. 配置文件
spring.elasticsearch.rest.uris=http://192.168.188.100:9200
3.测试类
@SpringBootTest public class MyTest { @Autowired RestHighLevelClient client; @Test public void add()throws Exception{ //如果不加id()则随机产生id IndexRequest req =new IndexRequest("user").id("10"); //方法一: //req.source("name","a1","age","101"); //方法二: User u=new User("a10",15); req.source(JSON.toJSONString(u),XContentType.JSON); IndexResponse resp = client.index(req, RequestOptions.DEFAULT); System.out.println(resp.status()); } @Test public void search()throws Exception{ SearchRequest req = new SearchRequest("user"); SearchSourceBuilder sb = new SearchSourceBuilder(); sb.query(QueryBuilders.matchAllQuery()).from(0).size(2).sort("age", SortOrder.DESC); req.source(sb); SearchResponse resp = client.search(req, RequestOptions.DEFAULT); SearchHit[] hits = resp.getHits().getHits(); for (SearchHit hit : hits) { //json字符串 // System.out.println(hit.getSourceAsMap()); //转java对象 System.out.println(JSON.parseObject(hit.getSourceAsString(), User.class)); } } @Test public void delete()throws Exception{ DeleteRequest req=new DeleteRequest("user","zwk9_noBPF1Cw_Bi_j-0"); DeleteResponse resp = client.delete(req, RequestOptions.DEFAULT); System.out.println(resp.status()); } @Test public void update()throws Exception{ UpdateRequest req =new UpdateRequest("user","2"); req.doc("name","张三","age",1000); UpdateResponse resp = client.update(req, RequestOptions.DEFAULT); System.out.println(resp.status()); } }
posted on 2021-10-31 17:38 JavaCoderPan 阅读(20) 评论(0) 编辑 收藏 举报 来源
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性