目录
- 1、Solr的概述
- 2、Solr的安装
- 3、Solr的命令
- 4、创建核心数据库
- 4.1、命令行方式
- 4.2、图形化方式
- 5、添加中文分词器
- 5.1、添加内置分词器
- 5.2、添加外部分词器
- 6、导入外部数据
- 6.1、手动导入单条的数据
- 6.2、批量导入数据库数据
- 6.2.1、准备数据库
- 6.2.2、配置数据库
- 6.2.3、配置普通域
- 6.2.4、配置复制域
- 6.2.5、配置动态域
- 6.2.6、导所有数据
- 7、配置安全账户
- 8、手写代码访问
- 8.1、创建工程
- 8.2、删除全部数据
- 8.3、添加一条数据
- 8.4、查询一条数据
- 8.5、修改一条数据
- 8.6、删除一条数据
- 8.7、导入全部数据
- 8.8、分页查询数据
- 8.9、条件查询数据
- 8.10、排序查询数据
- 8.11、高亮查询数据
配套资料,免费下载
链接:https://pan.baidu/s/1jA217UgqXpONi_fV-aOzqw
提取码:bm2g
复制这段内容后打开百度网盘手机App,操作更方便哦
1、Solr的概述
大多数搜索引擎应用都必须具有某种搜索功能,问题是搜索功能往往是巨大的资源消耗并且它们由于沉重的数据库加载而拖垮你的应用的性能。这就是为什么转移负载到一个外部的搜索服务器是一个不错的主意,Apache Solr是一个流行的开源搜索服务器,它通过使用类似REST的HTTP API,这就确保你能从几乎任何编程语言来使用Solr。Solr是一个开源搜索平台,用于构建搜索应用程序。 它建立在Lucene(全文搜索引擎)之上。 Solr是企业级的,快速的和高度可扩展的。 使用Solr构建的应用程序非常复杂,可提供高性能。
为了在CNET网络的公司网站上添加搜索功能,Yonik Seely于2004年创建了Solr。并在2006年1月,它成为Apache软件基金会下的一个开源项目。并于2016年发布最新版本Solr 6.0,支持并行SQL查询的执行。Solr可以和Hadoop一起使用。由于Hadoop处理大量数据,Solr帮助我们从这么大的源中找到所需的信息。不仅限于搜索,Solr也可以用于存储目的。像其他NoSQL数据库一样,它是一种非关系数据存储和处理技术。总之,Solr是一个可扩展的,可部署,搜索/存储引擎,优化搜索大量以文本为中心的数据。
2、Solr的安装
下载地址:https://lucene.apache/solr/downloads.html
解压Solr:我这里解压到桌面上
启动Solr:solr start
打开Solr:http://localhost:8983/solr/
3、Solr的命令
启动solr
- bin/solr start -help 查看start帮助
- bin/solr start 启动单机版
- bin/solr start -f 前台启动
- bin/solr start -p 8984 指定端口启动
- bin/solr restart 重启项目,如果不能重启,请先全部关闭,然后再启动
- bin/solr start -cloud 启动分布式版本
- bin/solr start -e cloud -noprompt -e表示要启动一个现有的例子,例子名称是cloud,cloud这个例子是以SolrCloud方式启动的
停止solr
- bin/solr stop -all 停止solr
查看solr状态
- bin/solr status 查看solr状态
创建solr核心
如果是单机版要创建core,如果是分布式的要创建collection
-
bin/solr create -help 查看create帮助
bin/solr create -c abc 创建名称为abc的核心,abc是core还是collection,取决于solr是单机版还是cloud版本
删除solr核心
- bin/solr delete -c abc 删除一个core或collection
4、创建核心数据库
核心可以理解为数据库,而核心里边的document可以理解为表。
4.1、命令行方式
1、打开dos命令窗口,切换目录到${solr.home}\bin,然后输入:solr create -c 核心名称,我这里输入的核心名称是core1之后回车;
2、打开solr安装文件,在/server/solr下就会出现新的文件夹core1(就是新创建的core1);
3、打开浏览器,输入solr访问路径:http://localhost:8983/solr,就会看到新建的core
4.2、图形化方式
1、直接在/server/solr下创建新文件夹,名字自定义,此处命名为core2,作为新建的core;
2、找到/server/solr/configsets/_default目录下的conf文件夹,然后拷贝一份到/server/solr/core2目录节点下。
3、然后按照下图操作:
5、添加中文分词器
因为solr是外国人开发的,对中文的支持并不是很好,很多单词都不能解析,这时候我们需要增加中文分词器,对中文单词进行分词处理,提高搜索准确度。
5.1、添加内置分词器
(1)在solr安装文件夹下面找到这个lucene-analyzers-smartcn-8.7.0.jar包
(2)复制一份到 solr-8.7.0\server\solr-webapp\webapp\WEB-INF\lib
这个目录下面
(3)接下来在你的项目conf下的配置文件managed-schema最后添加以下配置,我们这里为 core1
核心进行配置
<!-- ChineseAnalyzer 自带的中文分词器 -->
<fieldType name="text_cn" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.smart.HMMChineseTokenizerFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.smart.HMMChineseTokenizerFactory"/>
</analyzer>
</fieldType>
这样就配置好了类型名称是 text_cn
的分词器。
(4)重启solr服务,查看分词效果
未分词前效果:
已分词后效果:
5.2、添加外部分词器
(1)先下载solr8版本的ik分词器,下载地址:https://search.maven/search?q=com.github.magese
(2)将下载好的jar包放入 solr-8.7.0\server\solr-webapp\webapp\WEB-INF\lib
目录中,下载速度可能会有点慢,如果下载失败,请到配套资料中获取
(3)接下来在你的项目conf下的配置文件managed-schema最后添加以下配置,我们这里为 core1
核心进行配置
<!-- ChineseAnalyzer 外部的中文分词器 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
这样就配置好了类型名称是 text_ik
的分词器。
(4)重启solr服务,查看分词效果
未分词前效果:
已分词后效果:
6、导入外部数据
solr是一个全文检索软件,既然要进行全文检索,那肯定需要很多数据才有必要使用solr全文检索,在这里,我将要给大家介绍两种常见的数据导入。
6.1、手动导入单条的数据
打开页面:http://localhost:8983/solr/#/core1/documents
复制内容:
{
"item_id":"40001",
"item_title":"苹果 iPhone 12 Pro Max",
"item_price":"12758.00",
"item_image":"https://img.alicdn/imgextra/i3/1710936647/O1CN01amGTkj1yyNHgrUWAv_!!0-item_pic.jpg_430x430q90.jpg",
"item_brand":"苹果",
"item_category":"手机",
"item_seller":"苹果官方旗舰店",
"item_goods_id":"4"
}
提交内容:
查询内容:http://localhost:8983/solr/#/core1/query
6.2、批量导入数据库数据
6.2.1、准备数据库
打开本地的mysql数据库,执行以下代码:
DROP DATABASE IF EXISTS `test` ;
CREATE DATABASE `test` ;
USE `test` ;
DROP TABLE IF EXISTS `item` ;
CREATE TABLE `item` (
`id` BIGINT (20) NOT NULL COMMENT '商品SKUID',
`title` VARCHAR (64) NOT NULL COMMENT '商品标题',
`price` DOUBLE NOT NULL COMMENT '商品价格',
`image` VARCHAR (255) NOT NULL COMMENT '商品图片',
`spec` VARCHAR (255) NOT NULL COMMENT '商品规格',
`brand` VARCHAR (32) NOT NULL COMMENT '商品品牌',
`category` VARCHAR (32) NOT NULL COMMENT '商品分类',
`seller` VARCHAR (32) NOT NULL COMMENT '商品卖家',
`goods_id` BIGINT (20) NOT NULL COMMENT '商品SPUID',
`is_deleted` INT (11) NOT NULL DEFAULT '0' COMMENT '是否删除(0:不删除,1:已删除)',
`last_modified` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间(最后一次数据修改时间)',
PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8 COMMENT = '商品明细表' ;
INSERT INTO `item` (
`id`,
`title`,
`price`,
`image`,
`spec`,
`brand`,
`category`,
`seller`,
`goods_id`,
`is_deleted`,
`last_modified`
)
VALUES
(
10000,
'【新品热卖中】Redmi Note 0 Pro',
100,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"联通2G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:50:45'
),
(
10001,
'【新品热卖中】Redmi Note 1 Pro',
201,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"32G\",\"网络\":\"联通3G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:50:49'
),
(
10002,
'【新品热卖中】Redmi Note 2 Pro',
302,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"联通4G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:50:51'
),
(
10003,
'【新品热卖中】Redmi Note 3 Pro',
403,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"联通5G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:50:53'
),
(
10004,
'【新品热卖中】Redmi Note 4 Pro',
504,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"32G\",\"网络\":\"联通2G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:50:55'
),
(
10005,
'【新品热卖中】Redmi Note 5 Pro',
605,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"联通3G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:50:57'
),
(
10006,
'【新品热卖中】Redmi Note 6 Pro',
706,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"联通4G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:51:00'
),
(
10007,
'【新品热卖中】Redmi Note 7 Pro',
807,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"32G\",\"网络\":\"联通5G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:51:01'
),
(
10008,
'【新品热卖中】Redmi Note 8 Pro',
908,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"联通3G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:51:03'
),
(
10009,
'【新品热卖中】Redmi Note 9 Pro',
999,
'https://img.alicdn/imgextra/i2/1714128138/O1CN01YOG4Ue29zFpwZ5cdD_!!1714128138.png_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"联通3G\"}',
'小米',
'手机',
'小米官方旗舰店',
1,
0,
'2021-01-10 13:51:05'
),
(
20000,
'【回馈老用户】Mate 40 pro+',
10499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:07'
),
(
20001,
'【回馈老用户】Mate 41 pro+',
11499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:08'
),
(
20002,
'【回馈老用户】Mate 42 pro+',
12499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:11'
),
(
20003,
'【回馈老用户】Mate 43 pro+',
13499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:13'
),
(
20004,
'【回馈老用户】Mate 44 pro+',
14499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"64G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:14'
),
(
20005,
'【回馈老用户】Mate 45 pro+',
15499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:16'
),
(
20006,
'【回馈老用户】Mate 46 pro+',
16499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:17'
),
(
20007,
'【回馈老用户】Mate 47 pro+',
17499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:19'
),
(
20008,
'【回馈老用户】Mate 48 pro+',
18499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:21'
),
(
20009,
'【回馈老用户】Mate 49 pro+',
19499,
'https://img.alicdn/imgextra/i4/2215302589/O1CN01HvJj3E1Uzo2riFgSG_!!0-item_pic.jpg_430x430q90.jpg',
'{\"机身内存\":\"16G\",\"网络\":\"移动5G\"}',
'华为',
'手机',
'华为官方旗舰店',
2,
0,
'2021-01-10 13:51:22'
),
(
30000,
'【高端精品机】液晶彩色电视机 50寸',
5990,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"50英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:24'
),
(
30001,
'【高端精品机】液晶彩色电视机 51寸',
5991,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"51英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:26'
),
(
30002,
'【高端精品机】液晶彩色电视机 52寸',
5992,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"52英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:27'
),
(
30003,
'【高端精品机】液晶彩色电视机 53寸',
5993,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"53英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:29'
),
(
30004,
'【高端精品机】液晶彩色电视机 54寸',
5994,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"54英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:31'
),
(
30005,
'【高端精品机】液晶彩色电视机 55寸',
5999,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"55英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:33'
),
(
30006,
'【高端精品机】液晶彩色电视机 56寸',
5999,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"56英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:34'
),
(
30007,
'【高端精品机】液晶彩色电视机 57寸',
5999,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"57英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:37'
),
(
30008,
'【高端精品机】液晶彩色电视机 58寸',
5999,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"58英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:38'
),
(
30009,
'【高端精品机】液晶彩色电视机 59寸',
5999,
'https://img.alicdn/imgextra/i2/2616970884/O1CN01bzBHDl1IOulmPgSgp_!!2616970884.jpg_430x430q90.jpg',
'{\"电视屏幕尺寸\":\"59英寸\"}',
'三星',
'电视',
'三星官方旗舰店',
3,
0,
'2021-01-10 13:51:40'
) ;
6.2.2、配置数据库
(1)编写solr和mysql的映射关系
拷贝以下内容,直接粘贴到该文件的最后部分:(solrconfig.xml)
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">db-data-config.xml</str>
</lst>
</requestHandler>
创建映射配置,直接粘贴到该文件的开始部分:(db-data-config.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<!--
配置数据源:
driver :数据库驱动
url :数据库连接
user :数据库用户
password :数据库密码
-->
<dataSource driver="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/test" user="root" password="root" />
<document>
<!--
配置数据表:
name :实体对应表名
pk :主键对应字段
query :全部导入语句
deltaQuery :查询出所有经过修改(通过时间判断)的记录主键id
deletedPKQuery :查询出所有经过删除(通过字段标记)的记录主键id
deltaImportQuery:增量导入语句,id来源于以上两条语句,对索引库进行更新操作,可能是删除,添加,修改
-->
<entity
name="item"
pk="id"
query="select * from item where is_deleted = 0"
deltaQuery="select id from item where last_modified > '${dataimporter.last_index_time}+8'"
deletedPkQuery="select id from item where is_deleted = 1"
deltaImportQuery="select * from item where id = '${dataimporter.delta.id}'"
>
<!--
配置数据域:
column :数据库中字段的名称,特别要注意,name="id"中的id才是solr内置的域名,本配置其余id均为数据库字段主键id
name :solr普通域的字段名
-->
<field column="id" name="id" />
<field column="title" name="item_title" />
<field column="price" name="item_price" />
<field column="image" name="item_image" />
<field column="brand" name="item_brand" />
<field column="category" name="item_category" />
<field column="seller" name="item_seller" />
<field column="goods_id" name="item_goods_id" />
<field column="is_deleted" name="item_is_deleted" />
<field column="last_modified" name="item_last_modified" />
</entity>
</document>
</dataConfig>
(2)拷贝solr连mysql的相关jar包
6.2.3、配置普通域
属性 | 描述 | 取值 | 默认 |
stored | 如果为true,该字段的实际值将在查询后显示出来 | true/false | true |
indexed | 如果为true,则可以在查询中使用该字段的值来检索匹配的文档。 | true/false | true |
uninvertible | 如果为true,则表示indexed=“true” docValues="false"在查询时字段可以“un-inverted”以构建大内存数据结构以代替DocValues。 出于历史原因,默认为true,但强烈建议用户将其设置false为稳定性并docValues="true"根据需要使用。 | true/false | true |
docValues | 如果为true,则字段的值将会放在面向列的DocValues结构中 | true/false | false |
multiValued | 如果为true,则表示单个文档可能包含此字段类型的多个值 | true/false | false |
required | 指示Solr拒绝任何添加没有此字段值的文档的尝试。此属性默认为false。 | true/false | false |
omitNorms | 如果为true,则省略与此字段关联的规范(这将禁用字段的长度规范化,并节省一些内存)。对于所有原始(未分析)字段类型,例如int,float,data,bool和string,默认为true。只有全文字段或字段需要规范。 | true/false | false |
omitTermFreqAndPositions | 如果为true,则忽略此字段的词频率,位置和有效负载。对于不需要该信息的字段,这可以提高性能。它还减少了索引所需的存储空间。依赖于使用此选项在字段上发出的位置的查询将无法查找文档。对于非文本字段的所有字段类型,此属性默认为true | true/false | false |
omitPositions | 类似omitTermFreqAndPositions但保留词频率信息 | true/false | false |
termVectors termPositions termOffsets termPayloads | 这些选项指示Solr维护每个文档的完整词向量,可选地包括这些向量中每个词出现的位置,偏移和有效负载信息。这些可用于加速突出显示和其他辅助功能,但在索引大小方面施加了相当大的成本。它们对于Solr的典型用途不是必需的 | true/false | false |
sortMissingFirst sortMissingLast | 排序结果时,Solr会列出那些排在搜索结果最前面的/最后面的,但该字段却没有取值的文档 | true/false | false |
配置普通域,直接粘贴到该文件的最后部分:(managed-schema)
<!--配置普通域-->
<field name="item_title" type="text_ik" indexed="true" stored="true"/>
<field name="item_price" type="pdouble" indexed="true" stored="true" docValues="false"/>
<field name="item_image" type="string" indexed="false" stored="true" />
<field name="item_brand" type="string" indexed="true" stored="true" />
<field name="item_category" type="string" indexed="true" stored="true" />
<field name="item_seller" type="text_ik" indexed="true" stored="true" />
<field name="item_goods_id" type="plong" indexed="true" stored="true" />
<field name="item_is_deleted" type="pint" indexed="true" stored="true" />
<field name="item_last_modified" type="pdate" indexed="true" stored="true" />
6.2.4、配置复制域
复制域常用于多域搜索,如:电商项目中搜索商品,既要在标题域中搜索也要在品牌域中搜索,传统的做法需要手工写两次,而solr想发送一次请求,可到两个域中搜索,为此,引入了复制域的概念,将两个域的域名复制到一个域中。
配置复制域,直接粘贴到该文件的最后部分:(managed-schema)
<!--配置复制域-->
<field name="item_keywords" type="text_ik" indexed="true" stored="false" multiValued="true"/>
<copyField source="item_title" dest="item_keywords"/>
<copyField source="item_brand" dest="item_keywords"/>
<copyField source="item_category" dest="item_keywords"/>
<copyField source="item_seller" dest="item_keywords"/>
6.2.5、配置动态域
当我们需要动态扩充字段时,我们需要使用动态域。对于电商系统来说,规格的值是不确定的,所以我们需要使用动态域来实现。
配置动态域,直接粘贴到该文件的最后部分:(managed-schema)
<!--配置动态域-->
<dynamicField name="item_spec_*" type="string" indexed="true" stored="true" />
6.2.6、导所有数据
(1)重启solr系统
(2)导入指定数据库中的数据(这种导入方式无法导入动态域,动态域需要手写代码实现)
全量导入:全部正常数据
solr执行:
solr查看:
增量导入:删除部分数据
mysql执行:
UPDATE item SET is_deleted = 1 WHERE brand = '小米';
solr执行:
solr查看:
增量导入:添加部分数据
mysql执行:
INSERT INTO `test`.`item` (`id`, `title`, `price`, `image`, `spec`, `brand`, `category`, `seller`, `goods_id`)
VALUES ('40001', '苹果手机', '1999', 'apple.jpg', '{\"屏幕大小\":\"6寸\",“网络”:\"电信4G\"}', '苹果', '手机', '苹果官方旗舰店', '4');
solr执行:
solr查看:
7、配置安全账户
(1)打开路径:solr-8.7.0\server\etc
,在此目录下新建 verify.properties 配置文件
#用户名: 密码,权限
admin: admin,admin
user1: pass1,admin
user2: pass2,admin
(2)打开路径:solr-8.7.0\server\contexts
,在文件configure中添加获取用户文件的配置,内容如下:
<Get name="securityHandler">
<Set name="loginService">
<New class="org.eclipse.jetty.security.HashLoginService">
<Set name="name">verify—name</Set>
<Set name="config"><SystemProperty name="jetty.home" default="."/>/etc/verify.properties</Set>
</New>
</Set>
</Get>
(3)打开路径:solr-8.7.0\server\solr-webapp\webapp\WEB-INF
在文件中找到security-constraint的配置,内容如下:
<!-- Get rid of error message -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Disable TRACE</web-resource-name>
<url-pattern>/</url-pattern>
<http-method>TRACE</http-method>
</web-resource-collection>
<auth-constraint/>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Enable everything but TRACE</web-resource-name>
<url-pattern>/</url-pattern>
<http-method-omission>TRACE</http-method-omission>
</web-resource-collection>
</security-constraint>
在上边这段代码下边加入以下代码用于权限校验,内容如下:
<security-constraint>
<web-resource-collection>
<web-resource-name>Solr Admin TRACE</web-resource-name>
<url-pattern>/</url-pattern>
<http-method-omission>TRACE</http-method-omission>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>verify-name</realm-name>
</login-config>
<security-role>
<role-name>admin</role-name>
<description>Solr Admin</description>
</security-role>
(4)重新启动solr,访问地址:http://localhost:8983/solr/
8、手写代码访问
8.1、创建工程
(1)添加相关依赖
<properties>
<java.version>1.8</java.version>
<mysql.version>5.1.49</mysql.version>
</properties>
...
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
(2)添加相关配置
spring:
data:
solr:
host: http://user1:pass1@localhost:8983/solr
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: root
(3)配置实体对象(solr与实体之间的关系)
com.caochenlei.integrationsolr.entity.Item
@Data
public class Item implements Serializable {
@Field("id")
private Long id;
@Field("item_title")
private String title;
@Field("item_price")
private Double price;
@Field("item_image")
private String image;
@Dynamic
@Field("item_spec_*")
private Map<String, String> spec;
@Field("item_brand")
private String brand;
@Field("item_category")
private String category;
@Field("item_seller")
private String seller;
@Field("item_goods_id")
private Long goodsId;
@Field("item_is_deleted")
private Integer isDeleted;
@Field("item_last_modified")
private Date lastModified;
}
(4)新建配置对象(solrClient需要重新设置)
com.caochenlei.integrationsolr.config.SolrTemplateConfig
@Component
public class SolrTemplateConfig {
@Bean
public HttpSolrClient solrClient(SolrProperties solrProperties) {
HttpClient httpClient = new SystemDefaultHttpClient();
return new HttpSolrClient.Builder(solrProperties.getHost()).withHttpClient(httpClient).build();
}
@Bean
public SolrTemplate solrTemplate(SolrClient solrClient) {
return new SolrTemplate(solrClient);
}
}
(5)注入模板对象
com.caochenlei.integrationsolr.IntegrationSolrApplicationTests
@SpringBootTest
class IntegrationSolrApplicationTests {
@Autowired
private SolrTemplate solrTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
//核心名称
private static final String CORE_NAME = "core1";
}
8.2、删除全部数据
@Test
void testDeleteAll() throws Exception {
SimpleQuery query = new SimpleQuery("*:*");
solrTemplate.delete(CORE_NAME, query);
solrTemplate.commit(CORE_NAME);
}
8.3、添加一条数据
@Test
void testAdd() throws Exception {
//添加动态域内容,Solr7之后版本的动态域,不能使用中文作为拼接索引
Map<String, String> spec = new HashMap<String, String>();
spec.put(URLEncoder.encode("屏幕尺寸", "UTF-8"), "19寸");
spec.put(URLEncoder.encode("内存大小", "UTF-8"), "16G");
Item item = new Item();
item.setId(50001L);
item.setTitle("外星人笔记本");
item.setPrice(19999.00);
item.setImage("alien.jpg");
item.setSpec(spec);
item.setBrand("外星人");
item.setCategory("笔记本");
item.setSeller("外星人官方旗舰店");
item.setGoodsId(5L);
item.setIsDeleted(0);
item.setLastModified(new Date());
solrTemplate.saveBean(CORE_NAME, item);
solrTemplate.commit(CORE_NAME);
}
8.4、查询一条数据
@Test
void testGetById() throws Exception {
Optional<Item> itemOptional = solrTemplate.getById(CORE_NAME, 50001L, Item.class);
Item item = itemOptional.get();
System.out.println(item.getId());
System.out.println(item.getTitle());
System.out.println(item.getPrice());
System.out.println(item.getImage());
Map<String, String> spec = item.getSpec();
Set<Map.Entry<String, String>> specEntries = spec.entrySet();
for (Map.Entry<String, String> specEntry : specEntries) {
String specName = specEntry.getKey().replace("_","%");
String specValue = specEntry.getValue();
System.out.println(URLDecoder.decode(specName, "UTF-8") + ":" + specValue);
}
System.out.println(item.getBrand());
System.out.println(item.getCategory());
System.out.println(item.getSeller());
System.out.println(item.getGoodsId());
System.out.println(item.getIsDeleted());
System.out.println(item.getLastModified());
}
8.5、修改一条数据
@Test
void testUpdate() throws Exception {
//添加动态域内容,Solr7之后版本的动态域,不能使用中文作为拼接索引
Map<String, String> spec = new HashMap<String, String>();
spec.put(URLEncoder.encode("屏幕尺寸", "UTF-8"), "19寸");
spec.put(URLEncoder.encode("内存大小", "UTF-8"), "16G");
Item item = new Item();
item.setId(50001L);
item.setTitle("外星人电视机");
item.setPrice(19999.00);
item.setImage("alien.jpg");
item.setSpec(spec);
item.setBrand("外星人");
item.setCategory("电视机");
item.setSeller("外星人官方旗舰店");
item.setGoodsId(5L);
item.setIsDeleted(0);
item.setLastModified(new Date());
solrTemplate.saveBean(CORE_NAME, item);
solrTemplate.commit(CORE_NAME);
}
8.6、删除一条数据
@Test
void testDeleteById() throws Exception {
solrTemplate.deleteByIds(CORE_NAME, "50001");
solrTemplate.commit(CORE_NAME);
}
8.7、导入全部数据
@Test
void testImportAll() throws Exception {
//查询出所有数据
String sql = "select * from item where is_deleted = 0";
List<Item> items = jdbcTemplate.query(sql, new RowMapper<Item>() {
@Override
public Item mapRow(ResultSet resultSet, int i) {
Item item = new Item();
try {
item.setId(resultSet.getLong("id"));
item.setTitle(resultSet.getString("title"));
item.setPrice(resultSet.getDouble("price"));
item.setImage(resultSet.getString("image"));
Map<String, String> spec = new HashMap<String, String>();
String specJSON = resultSet.getString("spec");
Map specMap = JSON.parseObject(specJSON);
Set<Map.Entry<String, String>> specEntries = specMap.entrySet();
for (Map.Entry<String, String> specEntry : specEntries) {
String specName = URLEncoder.encode(specEntry.getKey(), "UTF-8");
String specValue = specEntry.getValue();
spec.put(specName, specValue);
}
item.setSpec(spec);
item.setBrand(resultSet.getString("brand"));
item.setCategory(resultSet.getString("category"));
item.setSeller(resultSet.getString("seller"));
item.setGoodsId(resultSet.getLong("goods_id"));
item.setIsDeleted(resultSet.getInt("is_deleted"));
item.setLastModified(resultSet.getDate("last_modified"));
} catch (Exception e) { e.printStackTrace(); }
return item;
}
});
//导入所有数据
solrTemplate.saveBeans(CORE_NAME, items);
solrTemplate.commit(CORE_NAME);
}
8.8、分页查询数据
@Test
void testGetByPage() throws Exception {
int pageCurr = 1;
int pageSize = 20;
SimpleQuery query = new SimpleQuery("*:*");
query.setOffset(Long.valueOf((pageCurr - 1) * pageSize));
query.setRows(pageSize);
ScoredPage<Item> items = solrTemplate.queryForPage(CORE_NAME, query, Item.class);
System.out.println("总页数:" + items.getTotalPages());
System.out.println("总记录:" + items.getTotalElements());
for (Item item : items) {
System.out.println(item);
}
}
8.9、条件查询数据
@Test
void testGetByCriteria() throws Exception {
int pageCurr = 1;
int pageSize = 20;
SimpleQuery query = new SimpleQuery("*:*");
query.setOffset(Long.valueOf((pageCurr - 1) * pageSize));
query.setRows(pageSize);
Criteria criteria = new Criteria("item_title").contains("Pro");
criteria = criteria.and("item_price").greaterThanEqual(15000);
criteria = criteria.and("item_price").lessThanEqual(18000);
query.addCriteria(criteria);
ScoredPage<Item> items = solrTemplate.queryForPage(CORE_NAME, query, Item.class);
System.out.println("总页数:" + items.getTotalPages());
System.out.println("总记录:" + items.getTotalElements());
for (Item item : items) {
System.out.println(item);
}
}
8.10、排序查询数据
@Test
void testGetBySort() throws Exception {
int pageCurr = 1;
int pageSize = 20;
SimpleQuery query = new SimpleQuery("*:*");
query.setOffset(Long.valueOf((pageCurr - 1) * pageSize));
query.setRows(pageSize);
query.addSort(Sort.by(Sort.Direction.DESC, "item_goods_id"));
ScoredPage<Item> items = solrTemplate.queryForPage(CORE_NAME, query, Item.class);
System.out.println("总页数:" + items.getTotalPages());
System.out.println("总记录:" + items.getTotalElements());
for (Item item : items) {
System.out.println(item);
}
}
8.11、高亮查询数据
@Test
void testGetByHighlight() throws Exception {
int pageCurr = 1;
int pageSize = 20;
SimpleHighlightQuery query = new SimpleHighlightQuery();
query.setOffset(Long.valueOf((pageCurr - 1) * pageSize));
query.setRows(pageSize);
//设置高亮选项
HighlightOptions highlightOptions = new HighlightOptions();
highlightOptions.setSimplePrefix("<em style='color:red'>");
highlightOptions.setSimplePostfix("</em>");
query.setHighlightOptions(highlightOptions);
//设置搜索条件
Criteria criteria = new Criteria("item_keywords").contains("华为");
query.addCriteria(criteria);
HighlightPage<Item> items = solrTemplate.queryForHighlightPage(CORE_NAME, query, Item.class);
System.out.println("总页数:" + items.getTotalPages());
System.out.println("总记录:" + items.getTotalElements());
//获取高亮入口
List<HighlightEntry<Item>> highlighted = items.getHighlighted();
for (HighlightEntry<Item> itemHighlightEntry : highlighted) {
//获取原来对象
Item item = itemHighlightEntry.getEntity();
//获取高亮集合
List<HighlightEntry.Highlight> highlights = itemHighlightEntry.getHighlights();
for (HighlightEntry.Highlight highlight : highlights) {
//获取高亮域
Field field = highlight.getField();
//域可能多值
List<String> snipplets = highlight.getSnipplets();
for (String snipplet : snipplets) {
if ("item_title".equals(field.getName())) {
item.setTitle(snipplet);
}
if ("item_brand".equals(field.getName())) {
item.setBrand(snipplet);
}
if ("item_category".equals(field.getName())) {
item.setCategory(snipplet);
}
if ("item_seller".equals(field.getName())) {
item.setSeller(snipplet);
}
}
}
//输出高亮对象
System.out.println(item);
}
}
更多推荐
整合篇:零基础学习与使用Solr
发布评论