一、案例逻辑
1.1 solr搜索实现三步走实现
1,需要把商品的数据导入到Solr 里面 2,根据条件编写各种代码实现搜索 3,使用定时任务定时同步数据库和solr的数据【当然应该提供手动同步】
1.2 solr搜索说明
1.2.1 关键字搜索 copyField[数组]去完成
1.2.2 分页
1.2.3 过滤条件
1.2.4 排序
1.2.5 高亮
1.2.6 价格区间
二、准备数据库
jd-shop
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for goods
-- ----------------------------
DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '商品ID',
`name` varchar(300) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '商品名称',
`shopid` bigint(20) NULL DEFAULT NULL COMMENT '店铺id',
`oriprice` decimal(15, 2) NULL DEFAULT 0.00 COMMENT '原价',
`price` decimal(15, 2) NULL DEFAULT NULL COMMENT '现价',
`remark` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '简要描述,卖点等',
`content` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '详细描述',
`picture` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品主图',
`imgs` varchar(1000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品图片,以,分割',
`status` int(1) NULL DEFAULT 0 COMMENT '默认是1,表示正常状态, -1表示删除, 0下架',
`categoryid` bigint(20) UNSIGNED NULL DEFAULT NULL COMMENT '商品分类',
`salenum` int(11) NULL DEFAULT NULL COMMENT '销量',
`totalstocks` int(11) NULL DEFAULT 0 COMMENT '总库存',
`deliverymode` json NULL COMMENT '配送方式json',
`deliverytemplateid` bigint(20) NULL DEFAULT NULL COMMENT '运费模板id',
`createtime` datetime(0) NULL DEFAULT NULL COMMENT '录入时间',
`updatetime` datetime(0) NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0) COMMENT '修改时间',
`filters` json NULL COMMENT '{\"is_jd_express\":true,\"is_second-hand\":true,\"is_new\":true,\"is_to_pay\":true} 是否京东快递,是否二手,是否新品,是否支持货到付款',
PRIMARY KEY (`id`) USING BTREE,
INDEX `shop_id`(`shopid`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 95 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '商品' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES (1, 'Apple iPhone XS Max 移动联通电信4G手机 111111', 1, 0.00, 1.01, '6.5英寸大屏,支持双卡。', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 93, 0, 95, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 78, '2019-03-29 14:40:00', '2020-04-04 15:07:24', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (2, '兰蔻粉水清滢柔肤水400ml 爽肤水女保湿舒缓滋润嫩肤', 1, 0.00, 420.00, '好看耐穿', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 87, 0, 0, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 48, '2019-04-21 19:15:34', '2020-04-04 15:07:34', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (3, '【Dole都乐】菲律宾都乐非转基因木瓜1只 单只约410g', 1, 0.00, 26.00, '包邮 肉厚籽少 独具风味', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 95, 0, 0, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-04-21 21:56:38', '2020-04-04 15:07:34', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (4, '阿迪达斯官方 adidas 三叶草 NITE JOGGER 男子经典鞋BD7956', 1, 10.00, 1199.00, ' 运动鞋/休闲鞋', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 0, 88, 0, 0, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-04-21 22:10:04', '2020-04-04 15:07:35', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (5, '【Dole都乐】比利时Truval啤梨12只 进口水果新鲜梨 单果120g左右', 1, 0.00, 38.00, '好吃', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 95, 100, 15, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-04-22 16:43:33', '2020-04-04 15:07:36', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (6, '旗舰店官网 自拍神器 梵高定制', 1, 10.00, 6998.00, '梵高定制礼盒 全球限量发售 分期免息', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 85, 0, 99, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-04-23 15:43:26', '2020-04-04 15:07:36', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (7, '餐厅装饰画现代简约饭厅挂画墙面壁画好好吃饭', 1, 169.00, 169.00, '创意餐厅装饰画 好好吃饭', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 91, 0, 0, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-04-25 10:22:21', '2020-04-04 15:07:37', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (8, '阴阳师寮办秘制 月见和菓子 184克', 1, 0.00, 22.00, '三层夹心,Q弹有料', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 95, 0, 77, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-04-27 11:37:13', '2020-04-04 15:07:37', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (9, '旺仔牛奶', 2, 0.00, 100.00, '测试', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 95, 0, 0, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 48, '2019-05-22 10:39:49', '2020-04-04 15:07:38', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (10, '测试商品A', 1, 30.00, 30.00, '牛逼', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 95, 0, 30, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-05-23 17:23:11', '2020-04-04 15:07:38', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (11, '测试商品B', 1, 40.00, 40.00, 'BBBB', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 95, 0, 40, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-05-23 17:24:06', '2020-04-04 15:07:39', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (12, '测试商品C', 1, 60.00, 50.00, 'CCC', '<p>测试商品</p>', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 'https://img12.360buyimg.com/n7/jfs/t7297/154/3413903491/65679/45ae4902/59e42830N9da56c41.jpg', 1, 95, 0, 50, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 47, '2019-05-23 17:24:48', '2020-04-04 15:07:39', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (13, '华为鲸鱼手机', 1, 0.00, 0.00, '5G快速四摄高清', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/00/rBPi511H47aAEkS9AAD0Hf0JFCw449.jpg', 'http://47.101.176.118/g1/M00/00/00/rBPi511H47aAEkS9AAD0Hf0JFCw449.jpg', 1, 93, 0, 0, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 59, '2019-08-05 17:13:41', '2020-04-04 15:07:40', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (14, '鲸鱼', 1, 0.00, 0.00, '鲸鱼好吃的鲸鱼', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/00/rBPi511H8_KAWI_tAAAH1Pr_MrM101.jpg', 'http://47.101.176.118/g1/M00/00/00/rBPi511H8_KAWI_tAAAH1Pr_MrM101.jpg', 1, 96, 0, 0, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 59, '2019-08-05 17:17:31', '2020-04-04 15:07:40', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (15, '华为Mate 20 PRO', 1, 0.00, 1.00, '5G四摄索引麒麟980', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/00/rBPi511H9P6AW6-sAAD0Hf0JFCw913.jpg', 'http://47.101.176.118/g1/M00/00/00/rBPi511H9P6AW6-sAAD0Hf0JFCw913.jpg', 1, 93, 0, 4, '{\"hasUserPickUp\": false, \"hasShopDelivery\": true}', 59, '2019-08-05 17:24:15', '2020-04-04 15:07:41', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (16, '算法导论第四版', 1, 0.00, 11.00, '你学不会', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/00/rBPi511Tdt2Aa6pQAABcteVfoYk808.jpg', 'http://47.101.176.118/g1/M00/00/00/rBPi511Tdt2Aa6pQAABcteVfoYk808.jpg', 1, 94, 0, 11, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 10:58:09', '2020-04-04 15:07:41', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (17, '算法导论第四版', 1, 0.00, 11.00, '你学不会', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/00/rBPi511Tdt2Aa6pQAABcteVfoYk808.jpg', 'http://47.101.176.118/g1/M00/00/00/rBPi511Tdt2Aa6pQAABcteVfoYk808.jpg', 1, 94, 0, 11, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 10:58:10', '2020-04-04 15:07:42', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (18, '算法导论第N版', 1, 0.00, 1.00, '学不会', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/01/rBPi511TeU6AUZ1hAABcteVfoYk222.jpg', 'http://47.101.176.118/g1/M00/00/01/rBPi511TeU6AUZ1hAABcteVfoYk222.jpg', 1, 94, 0, 1, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 11:01:19', '2020-04-04 15:07:42', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (19, '锤子(smartisan) 坚果Pro3 8GB+128GB 黑色 骁龙855PLUS 4800万四摄 全网通双卡双待 全面屏游戏手机', 1, 2289.00, 2289.00, '稀缺货源,限量抢购】2K+90Hz流体屏,骁龙855旗舰,4800万超广角三摄,影音娱乐不在话下', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 1, 93, 0, 0, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 11:03:23', '2020-04-04 15:07:43', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (20, '荣耀9X 麒麟810 4000mAh续航 4800万超清夜拍 6.59英寸升降全面屏 全网通6GB+64GB 魅海蓝', 1, 1289.00, 1289.00, '稀缺货源,限量抢购】2K+90Hz流体屏,骁龙855旗舰,4800万超广角三摄,影音娱乐不在话下', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 1, 93, 0, 0, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 11:03:23', '2020-04-04 15:07:43', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (21, 'Apple iPhone 11 (A2223) 128GB 黑色 移动联通电信4G手机 双卡双待', 1, 5999.00, 5999.00, '稀缺货源,限量抢购】2K+90Hz流体屏,骁龙855旗舰,4800万超广角三摄,影音娱乐不在话下', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 1, 93, 0, 0, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 11:03:25', '2020-04-04 15:07:43', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (22, '一加 OnePlus 7T 90Hz流体屏 骁龙855Plus旗舰 4800万超广角三摄 8GB+256GB 冰川银 全面屏拍照游戏手机', 1, 3199.00, 3199.00, '稀缺货源,限量抢购】2K+90Hz流体屏,骁龙855旗舰,4800万超广角三摄,影音娱乐不在话下', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 'http://47.101.176.118/g1/M00/00/01/rBPi511Ted6AV01_AABcteVfoYk963.jpg', 1, 93, 0, 0, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 11:05:43', '2020-04-04 15:07:45', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
INSERT INTO `goods` VALUES (23, '努比亚 nubia X 双面屏 深空灰 8GB+128GB 全网通 移动联通电信4G手机 双卡双待', 1, 2399.00, 2399.00, '【火爆销售中】双屏黑科技,骁龙845,AOD熄屏,双摄AI美颜自拍', '<p>测试商品</p>', 'http://47.101.176.118/g1/M00/00/01/rBPi511TeqGAdjQfAABcteVfoYk439.jpg', 'http://47.101.176.118/g1/M00/00/01/rBPi511TeqGAdjQfAABcteVfoYk439.jpg', 1, 85, 0, 1, '{\"hasUserPickUp\": true, \"hasShopDelivery\": false}', 47, '2019-08-14 11:07:04', '2020-04-04 15:07:44', '{\"is_new\": true, \"is_to_pay\": true, \"is_jd_express\": true, \"is_second_hand\": true}');
SET FOREIGN_KEY_CHECKS = 1;
updatetime 是最后做增加更新时使用
三、创建项目
3.1 springboot项目
3.2修改pom.xml添加Druid和mybatisplus的依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1.tmp</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
3.3 配置yml
#端口
server:
port: 8080
spring:
#数据源的配置
datasource:
url: jdbc:mysql://127.0.0.1:3306/jd-shop?serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
application:
name: jd-search
data:
solr:
host: http://47.95.34.202:8983/solr/jd-shop
#配置mybatisplus
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:mapper/*.xml
global-config:
db-config:
id-type: auto
3.4 使用插件生成Goods和GoodsMapper
3.4.1 准备工作
3.4.2 安装插件
https://zhile.io/2019/04/23/mybatis-code-helper-pro-crack.html
OK之后重启IDEA
3.4.3 生成Goods,GoodsMapper,XML
Goods
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "goods")
public class Goods {
/**
* 商品ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 商品名称
*/
@TableField(value = "name")
private String name;
/**
* 店铺id
*/
@TableField(value = "shopid")
private Long shopid;
/**
* 原价
*/
@TableField(value = "oriprice")
private BigDecimal oriprice;
/**
* 现价
*/
@TableField(value = "price")
private BigDecimal price;
/**
* 简要描述,卖点等
*/
@TableField(value = "remark")
private String remark;
/**
* 详细描述
*/
@TableField(value = "content")
private String content;
/**
* 商品主图
*/
@TableField(value = "picture")
private String picture;
/**
* 商品图片,以,分割
*/
@TableField(value = "imgs")
private String imgs;
/**
* 默认是1,表示正常状态, -1表示删除, 0下架
*/
@TableField(value = "status")
private Integer status;
/**
* 商品分类
*/
@TableField(value = "categoryid")
private Long categoryid;
/**
* 销量
*/
@TableField(value = "salenum")
private Integer salenum;
/**
* 总库存
*/
@TableField(value = "totalstocks")
private Integer totalstocks;
/**
* 配送方式json
*/
@TableField(value = "deliverymode")
private Object deliverymode;
/**
* 运费模板id
*/
@TableField(value = "deliverytemplateid")
private Long deliverytemplateid;
/**
* 录入时间
*/
@TableField(value = "createtime")
private Date createtime;
/**
* 修改时间
*/
@TableField(value = "updatetime")
private Date updatetime;
/**
* {"is_jd_express":true,"is_second-hand":true,"is_new":true,"is_to_pay":true} 是否京东快递,是否二手,是否新品,是否支持货到付款
*/
@TableField(value = "filters")
private Object filters;
public static final String COL_ID = "id";
public static final String COL_NAME = "name";
public static final String COL_SHOPID = "shopid";
public static final String COL_ORIPRICE = "oriprice";
public static final String COL_PRICE = "price";
public static final String COL_REMARK = "remark";
public static final String COL_CONTENT = "content";
public static final String COL_PICTURE = "picture";
public static final String COL_IMGS = "imgs";
public static final String COL_STATUS = "status";
public static final String COL_CATEGORYID = "categoryid";
public static final String COL_SALENUM = "salenum";
public static final String COL_TOTALSTOCKS = "totalstocks";
public static final String COL_DELIVERYMODE = "deliverymode";
public static final String COL_DELIVERYTEMPLATEID = "deliverytemplateid";
public static final String COL_CREATETIME = "createtime";
public static final String COL_UPDATETIME = "updatetime";
public static final String COL_FILTERS = "filters";
}
GoodsMapper
public interface GoodsMapper extends BaseMapper<Goods> {
}
GoodsMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.solr.mapper.GoodsMapper">
<resultMap id="BaseResultMap" type="com.example.solr.domain.Goods">
<!--@mbg.generated-->
<!--@Table goods-->
<id column="id" jdbcType="BIGINT" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="shopid" jdbcType="BIGINT" property="shopid" />
<result column="oriprice" jdbcType="DECIMAL" property="oriprice" />
<result column="price" jdbcType="DECIMAL" property="price" />
<result column="remark" jdbcType="VARCHAR" property="remark" />
<result column="content" jdbcType="LONGVARCHAR" property="content" />
<result column="picture" jdbcType="VARCHAR" property="picture" />
<result column="imgs" jdbcType="VARCHAR" property="imgs" />
<result column="status" jdbcType="INTEGER" property="status" />
<result column="categoryid" jdbcType="BIGINT" property="categoryid" />
<result column="salenum" jdbcType="INTEGER" property="salenum" />
<result column="totalstocks" jdbcType="INTEGER" property="totalstocks" />
<result column="deliverymode" jdbcType="OTHER" property="deliverymode" />
<result column="deliverytemplateid" jdbcType="BIGINT" property="deliverytemplateid" />
<result column="createtime" jdbcType="TIMESTAMP" property="createtime" />
<result column="updatetime" jdbcType="TIMESTAMP" property="updatetime" />
<result column="filters" jdbcType="OTHER" property="filters" />
</resultMap>
<sql id="Base_Column_List">
<!--@mbg.generated-->
id, `name`, shopid, oriprice, price, remark, content, picture, imgs, `status`, categoryid,
salenum, totalstocks, deliverymode, deliverytemplateid, createtime, updatetime, filters
</sql>
</mapper>
3.4.4 修改主启动类
@SpringBootApplication
@MapperScan(basePackages = {"com.example.solr.mapper"})
public class SolrSpringbootJdApplication {
public static void main(String[] args) {
SpringApplication.run(SolrSpringbootJdApplication.class, args);
}
}
3.4.5 测试mybatisplus和solr是否可用
四、在solr里面创建jd-shop的core并配置好属性
4.1 创建jd-shop
4.2 配置分词和属性[schema文件]
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" />
<field name="name" type="text_cn" indexed="true" stored="true" required="true" multiValued="false" />
<field name="shopid" type="plong" indexed="true" stored="true" multiValued="false" />
<field name="oriprice" type="pdouble" indexed="true" stored="true" multiValued="false" />
<field name="price" type="pdouble" indexed="true" stored="true" multiValued="false" />
<field name="remark" type="text_cn" indexed="true" stored="true" multiValued="false" />
<field name="content" type="text_cn" indexed="true" stored="true" multiValued="false" />
<field name="picture" type="string" indexed="false" stored="true" multiValued="false" />
<field name="categoryid" type="plong" indexed="true" stored="true" multiValued="false" />
<field name="salenum" type="pint" indexed="true" stored="true" multiValued="false" />
<field name="totalstocks" type="pint" indexed="true" stored="true" multiValued="false" />
<field name="is_jd_express" type="pint" indexed="true" stored="true" multiValued="false" />
<field name="is_second-hand" type="pint" indexed="true" stored="true" multiValued="false" />
<field name="is_new" type="pint" indexed="true" stored="true" multiValued="false" />
<field name="is_to_pay" type="pint" indexed="true" stored="true" multiValued="false" />
<field name="keywords" type="text_cn" indexed="true" stored="true" multiValued="true" />
<copyField source="name" dest="keywords" />
<copyField source="remark" dest="keywords" />
<!--添加一个中文分词器IK-->
<fieldType name="text_cn" class="solr.TextField" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="org.apache.lucene.analysis.ik.IKTokenizerFactory" useSmart="true"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.apache.lucene.analysis.ik.IKTokenizerFactory" useSmart="false"/>
</analyzer>
</fieldType>
覆盖到solr并重启
五、代码实现全量和增量导入
5.1 添加依赖并全量导入
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
ImportService接口
public interface ImportService {
/***
* @Description:
* @Param: 全量导入
*/
public void importAll();
/***
* @Description:
* @Param: 增量导入
*/
public void importUpdate();
}
ImportServiceImpl
@Service
@Transactional
public class ImportServiceImpl implements ImportService {
@Autowired
private GoodsMapper goodsMapper;
@Autowired
private SolrClient solrClient;
@Override
@PostConstruct //只要IOC容器加载就运行
public void importAll() {
//查询出所有上架的商品
QueryWrapper<Goods> qw=new QueryWrapper<>();
qw.eq("status",1);
List<Goods> goodsList = goodsMapper.selectList(qw);
List<SolrInputDocument> docs=this.createDoc(goodsList);
try {
solrClient.add(docs);
solrClient.commit();//提交
System.out.println("数据全量同步成功:"+new Date());
}catch (Exception e){
System.out.println(e);
}
}
/***
* @Description: 构造文档集合
* @Param: [goodsList]
*/
private List<SolrInputDocument> createDoc(List<Goods> goodsList) {
List<SolrInputDocument> docs=new ArrayList<>(goodsList.size());
for (Goods g : goodsList) {
SolrInputDocument doc=new SolrInputDocument();
doc.addField("id",g.getId().toString());
doc.addField("name",g.getName());
doc.addField("shopid",g.getShopid().longValue());
doc.addField("oriprice",g.getOriprice().doubleValue());
doc.addField("price",g.getPrice().doubleValue());
doc.addField("remark",g.getRemark());
doc.addField("content",g.getContent());
doc.addField("picture",g.getPicture());
doc.addField("categoryid",g.getCategoryid().longValue());
doc.addField("salenum",g.getSalenum().intValue());
doc.addField("totalstocks",g.getTotalstocks().intValue());
JSONObject jsonObject = JSON.parseObject(g.getFilters().toString());
doc.addField("is_jd_express",jsonObject.get("is_jd_express").equals(true)?1:0);
doc.addField("is_second_hand",jsonObject.get("is_second_hand").equals(true)?1:0);
doc.addField("is_new",jsonObject.get("is_new").equals(true)?1:0);
doc.addField("is_to_pay",jsonObject.get("is_to_pay").equals(true)?1:0);
docs.add(doc);
}
return docs;
}
@Override
public void importUpdate() {
}
}
去控制台查看数据即可。
5.2 增量导入
修改ImportServiceImpl
@Service
@Log4j2
@Transactional
public class ImportServiceImpl implements ImportService {
@Autowired
private GoodsMapper goodsMapper;
@Autowired
private SolrClient solrClient;
@Override
@PostConstruct //只要IOC容器加载就运行
public void importAll() {
//查询出所有上架的商品
QueryWrapper<Goods> qw=new QueryWrapper<>();
qw.eq("status",1);
List<Goods> goodsList = goodsMapper.selectList(qw);
List<SolrInputDocument> docs=this.createDoc(goodsList);
try {
solrClient.add(docs);
solrClient.commit();//提交
log.info("数据全量同步成功:"+new Date());
}catch (Exception e){
System.out.println(e);
log.warn("数据全量同步失败,{}",e);
}
this.lastSycnDate=new Date();
}
/***
* @Description: 构造文档集合
* @Param: [goodsList]
*/
private List<SolrInputDocument> createDoc(List<Goods> goodsList) {
List<SolrInputDocument> docs=new ArrayList<>(goodsList.size());
for (Goods g : goodsList) {
SolrInputDocument doc=new SolrInputDocument();
doc.addField("id",g.getId().toString());
doc.addField("name",g.getName());
doc.addField("shopid",g.getShopid().longValue());
doc.addField("oriprice",g.getOriprice().doubleValue());
doc.addField("price",g.getPrice().doubleValue());
doc.addField("remark",g.getRemark());
doc.addField("content",g.getContent());
doc.addField("picture",g.getPicture());
doc.addField("categoryid",g.getCategoryid().longValue());
doc.addField("salenum",g.getSalenum().intValue());
doc.addField("totalstocks",g.getTotalstocks().intValue());
JSONObject jsonObject = JSON.parseObject(g.getFilters().toString());
doc.addField("is_jd_express",jsonObject.get("is_jd_express").equals(true)?1:0);
doc.addField("is_second-hand",jsonObject.get("is_second-hand").equals(true)?1:0);
doc.addField("is_new",jsonObject.get("is_new").equals(true)?1:0);
doc.addField("is_to_pay",jsonObject.get("is_to_pay").equals(true)?1:0);
docs.add(doc);
}
return docs;
}
//声明一个最后一次的导入时间
private Date lastSycnDate=new Date();
@Override
@Scheduled(initialDelay = 5*1000,fixedRate = 5*1000) //延时5秒执行 5秒循环一次
public void importUpdate() {
//查询出所有上架的商品
QueryWrapper<Goods> qw=new QueryWrapper<>();
qw.eq("status",1);
qw.ge("updatetime",lastSycnDate);
List<Goods> goodsList = goodsMapper.selectList(qw);
List<SolrInputDocument> docs=this.createDoc(goodsList);
try {
solrClient.add(docs);
solrClient.commit();//提交
lastSycnDate=new Date();
log.info("数据增量导入成功:"+lastSycnDate.toLocaleString());
}catch (Exception e){
System.out.println(e);
log.warn("数据增量导入失败{}",e);
}
}
}
修改主启动类开启定时任务
@SpringBootApplication
@MapperScan(basePackages = {"com.example.solr.mapper"})
@EnableScheduling
public class SolrSpringbootJdApplication {
public static void main(String[] args) {
SpringApplication.run(SolrSpringbootJdApplication.class, args);
}
}
六、编写代码实现搜索
6.1 创建DataGridView
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DataGridView {
private Integer code=0;
private String msg="";
private Long count;
private Object data;
}
6.2 创建SearchService
public interface SearchService {
/***
* @Description:
* @Param: [keywords, 关键字
* page, 页码
* limit, 每页显示条数
* sort, 排序字段 1 价格 2 销量
* priceScope, 价格区间 200-300
* filters] "is_jd_express":1,
* "is_second-hand":1,
* "is_new":1,
* "is_to_pay":1,
* @return: DataGridView
*/
DataGridView searchGoods(String keywords, Integer page, Integer limit, Integer sort, String priceScope, Map<String,Object> filters);
}
6.3 创建SearchServiceImpl
@Service
@Log4j2
public class SearchServiceImpl implements SearchService {
@Autowired
private SolrClient solrClient;
/***
* @Description:
* @Param: [keywords, 关键字
* page, 页码
* limit, 每页显示条数
* sort, 排序字段 1 价格升 2 价格降 3 销量升 4 销量降
* priceScope, 价格区间 200-300
* filters] "is_jd_express":1,
* "is_second_hand":1,
* "is_new":1,
* "is_to_pay":1,
* @return: DataGridView
* @Author: 雷哥
* @Date: 2020/4/4
*/
@Override
public DataGridView searchGoods(String keywords, Integer page, Integer limit,
Integer sort, String priceScope, Map<String, Object> filters) {
//关键字
SolrQuery solrQuery=null;
if(StringUtils.isEmpty(keywords)){
solrQuery=new SolrQuery("*:*");
}else{
solrQuery=new SolrQuery("keywords:"+keywords);
}
//分页处理
solrQuery.setStart((page-1)*limit);
solrQuery.setRows(limit);
//处理排序
switch (sort){
case 1://按价格升
solrQuery.addSort("price",SolrQuery.ORDER.asc);
break;
case 2://按价格降
solrQuery.addSort("price",SolrQuery.ORDER.desc);
break;
case 3://按销量升
solrQuery.addSort("salenum",SolrQuery.ORDER.asc);
break;
case 4://按销量降
solrQuery.addSort("salenum",SolrQuery.ORDER.desc);
break;
}
//处理价格过滤
List<String> filterList=new ArrayList<>();
if(!StringUtils.isEmpty(priceScope)){
String[] split = priceScope.split("-");
if(split.length!=2){
throw new RuntimeException("传入的价格范围参数不合法");
}
filterList.add("price:["+split[0]+" TO "+split[1]+"]");
}
//处理其它过滤"is_jd_express":1,
// * "is_second_hand":1,
// * "is_new":1,
// * "is_to_pay":1,
if(!filters.isEmpty()){
for (Map.Entry<String, Object> entry : filters.entrySet()) {
filterList.add(entry.getKey()+":"+entry.getValue());
}
}
//添加过滤条件
if(!filterList.isEmpty()){
solrQuery.addFilterQuery(filterList.toArray(new String[]{}));
}
//只要关键字不为空才设置高亮
if(!StringUtils.isEmpty(keywords)){
solrQuery.setHighlight(true);
solrQuery.addHighlightField("name");
solrQuery.addHighlightField("remark");
solrQuery.setHighlightSimplePre("<font color=red>");
solrQuery.setHighlightSimplePost("</font>");
}
DataGridView dataGridView=new DataGridView();
List<Goods> goods=new ArrayList<>();
try
{
QueryResponse query = solrClient.query(solrQuery);
SolrDocumentList results = query.getResults();
dataGridView.setCount(results.getNumFound());//设置总条数
Map<String, Map<String, List<String>>> highlighting =null;
if(solrQuery.getHighlight()){//如果开户高亮,就高亮查询
highlighting=query.getHighlighting();
}
for (SolrDocument result : results) {
Goods g=new Goods();
g.setId(Long.valueOf(result.getFieldValue("id").toString()));
g.setName(result.getFieldValue("name").toString());
g.setShopid(Long.valueOf(result.getFieldValue("shopid").toString()));
g.setOriprice(new BigDecimal(Double.valueOf(result.getFieldValue("oriprice").toString())));
g.setPrice(new BigDecimal(Double.valueOf(result.getFieldValue("price").toString())));
g.setRemark(result.getFieldValue("remark").toString());
g.setContent(result.getFieldValue("content").toString());
g.setPicture(result.getFieldValue("picture").toString());
g.setCategoryid(Long.valueOf(result.getFieldValue("categoryid").toString()));
g.setSalenum(Integer.valueOf(result.getFieldValue("salenum").toString()));
g.setTotalstocks(Integer.valueOf(result.getFieldValue("totalstocks").toString()));
//处理高亮
if(solrQuery.getHighlight()){
if(null!=highlighting&&!highlighting.isEmpty()){
for (Map.Entry<String, Map<String, List<String>>> entry : highlighting.entrySet()) {
String key = entry.getKey();
Map<String, List<String>> value = entry.getValue();
if(value.containsKey("name")){
String hlName=value.get("name").get(0);
g.setName(hlName);
}
if(value.containsKey("remark")){
String hlRemark=value.get("remark").get(0);
g.setRemark(hlRemark);
}
}
}
}
goods.add(g);
}
}catch (Exception e){
log.warn("查询失败{}",e);
}
dataGridView.setData(goods);
return dataGridView;
}
}
6.4 测试
@SpringBootTest
class SolrSpringbootJdApplicationTests {
@Autowired
private SearchService searchService;
@Test
void contextLoads() {
Map<String, Object> filters=new HashMap<>();
filters.put("is_jd_express",1);//要求京东快递
DataGridView searchGoods = searchService.searchGoods("", 1, 5, 1, "70-500", filters);
List<Goods> data = (List<Goods>) searchGoods.getData();
for (Goods datum : data) {
System.out.println(datum);
}
}
}
七、Solr控制台全量和增量导入配置
7.1 清空solr里面的数据
7.2 导包
在solr安装目录下dist目录下有两个solr-dataimport**。.jar
引入mysql的驱动包
7.3 修改server/solr/jd-shop/conf/solrconfig.xml
<!--配置控制台的数据导入-->
<requestHandler name="/dataimport" class="org.apache.solr.handler.dataimport.DataImportHandler">
<lst name="defaults">
<str name="config">data-config.xml</str>
</lst>
</requestHandler>
7.4 创建server/solr/jd-shop/conf/data-conf.xml的文件
<?xml version="1.0" encoding="UTF-8" ?>
<dataConfig>
<!--配置数据源-->
<dataSource type="JdbcDataSource"
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/jd-shop?serverTimezone=UTC"
user="root"
password="123456"/>
<document>
<entity name="goods"
query="select id,name,shopid,oriprice,price,remark,content,picture,categoryid,salenum,totalstocks,
case JSON_EXTRACT(filters, '$.is_jd_express') WHEN true THEN 1 ELSE 0 END AS is_jd_express,
case JSON_EXTRACT(filters, '$.is_second_hand') WHEN true THEN 1 ELSE 0 END AS is_second_hand,
case JSON_EXTRACT(filters, '$.is_new') WHEN true THEN 1 ELSE 0 END AS is_new,
case JSON_EXTRACT(filters, '$.is_to_pay') WHEN true THEN 1 ELSE 0 END AS is_to_pay
FROM goods where status= 1;" >
<!--查询的数据和数据库索引意义对应column 是查询的字段name 是solr索引对应的字段
<field column="fid" name="fid"/> 因为已经使用As映射好了 不用加了-->
</entity>
</document>
</dataConfig>
7.5 在阿里云上使用docker运行一个mysql
docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
nvcat连接再把本地的数据库jd-shop上传到阿里云
7.6 把刚才修改和创建的两配置文件覆盖到solr配置
重启solr 并查看控制台
执行之后再查看数据
评论