java项目中用到的solr_Solr的原理及在项目中的使用实例.

本文介绍了在Java项目中如何使用Solr进行商品信息的检索和过滤。当商品上架时,商品信息会被同步到Solr库中,包括商品ID、名称、图片URL和价格等。在搜索时,Solr会根据输入的关键词进行高亮显示,并支持品牌和价格范围的过滤条件。同时,文章也提到了如何在Spring中管理SolrServer,以及利用Redis存储和查询商品品牌列表。
摘要由CSDN通过智能技术生成

前面已经讲过 如果安装及配置Solr服务器了, 那么现在我们就来正式在代码中使用Solr.

1,这里Solr主要是怎么使用的呢?

当我们在前台页面搜索商品名称关键词时, 我们这时是在Solr库中去查找相应的商品信息, 然后将搜索关键词高亮.

2,那么Solr库中的商品信息又是如何添加的呢?

当我们在给商品上架的时候, 将商品信息update 到mysql数据库中的bbs_product表中, 然后同样的将相应的信息 添加到Solr库中.

接下来就看代码的具体实现吧:

一, 商品上架

811ea8ec3501ecc917098435b812b01d.png

我们在这里点击上架按钮:

list.jsp:1 

点击上架触发isShow事件:

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

接着到Controller层:

ProductController.java:1 //添加页面2     @RequestMapping("/isShow.do")3     public String isShow(Long[] ids, Model model){4         productService.isShow(ids);5         return "forward:/product/list.do";6     }

接着看Service层:

ProdcutServiceImpl.java:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 //上架@Autowired

private SolrServer solrServer; 2     public void isShow(Long[] ids){ 3         Product product = new Product(); 4         product.setIsShow(true); 5         for (Long id : ids) { 6             //上下架状态 7             product.setId(id); 8             productDao.updateByPrimaryKeySelective(product); 9             10             //TODO 保存商品信息到Solr服务器11             SolrInputDocument doc = new SolrInputDocument();12             //ID13             doc.setField("id", id);14             //名称15             Product p = productDao.selectByPrimaryKey(id);16             doc.setField("name_ik", p.getName());17             //图片URL18             doc.setField("url", p.getImgUrls()[0]);19             //品牌 ID20             doc.setField("brandId", p.getBrandId());21             //价格 sql查询语句: select price from bbs_sku where product_id = ? order by price asc limit 122             SkuQuery skuQuery = new SkuQuery();23             skuQuery.createCriteria().andProductIdEqualTo(id);24             skuQuery.setOrderByClause("price asc");25             skuQuery.setPageNo(1);26             skuQuery.setPageSize(1);27             List skus = skuDao.selectByExample(skuQuery);28             doc.setField("price", skus.get(0).getPrice());29             //...时间等 剩下的省略30             31             try {32                 solrServer.add(doc);33                 solrServer.commit();34             } catch (Exception e) {35                 // TODO Auto-generated catch block36                 e.printStackTrace();37             }38             //TODO 静态化39         }40     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

这里使用SolrInputDocument 来保存商品信息, 其中doc.setField("name_ik", p.getName());的name_ik 是我们在solr 配置文件配置的IK 分词器的字段, doc.setField("url", p.getImgUrls()[0]); 这里我们也只是取第一张图片的url用来展示.

这里我们还用到了skuQuery, 因为一个商品中不同的颜色不同的尺码都可能有不同的价格, 我们在这里 是取到同一个productId下价格最小的来给显示~

然后再就是将我们已经设置好的SolrInputDocument通过SolrServer 来提交到Solr服务器. SolrServer是已经在spring中注册好了的, 在这里直接注入即可使用.

spring来管理Solr:

bbc810348826cbccd2b3b7bbc0c0b69e.png

到了这里上架的功能就做好了, 这也是给后面Solr查询做好铺垫.

二, 前台使用Solr查询到了这里就开始查看前台页面了, 前台页面是扒的网上的, 具体业务逻辑是自己修改的, 页面如下:

25bf52c89f85ffdf2e0405d6107a46d3.png

这里需要特殊说明一下, 我们配置的全局拦截器变成了: / , 而且过滤掉静态资源, 配置如下:

首先是babasport-portal project下的web.xml文件:

8f900a89c6347c561fdf2122f13be562.png View Code

第二个就是babasport-portal project下的spring配置文件中设置过滤掉静态资源:1 2     3     4     

这样就就可以直接访问了.

当我们输入2016 点击查询后会出现什么? 我把已经做好的页面展示一下:

9baa2a34b146237c00ef7239b4978916.png

那么就进入到实际的开发当中:

当我们在搜索框输入2016 且点击 搜索时:

5da0f84dd06759d7f2cf0a0d9fd1e3c5.png

然后到Controller层去找到search方法:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired 2     private SearchService searchService; 3      4     //去首页 5     @RequestMapping(value="/") 6     public String index(){ 7         return "index"; 8     } 9     10     //搜索11     @RequestMapping(value="/search")12     public String search(Integer pageNo, String keyword, String price, Long brandId,  Model model){13         //品牌结果集  Redis中14         List brands = searchService.selectBrandListFromRedis();15         model.addAttribute("brands", brands);16         17         //map 装已经选择的条件18         Map map = new HashMap();19         if(null != brandId){20             for (Brand brand : brands) {21                 if(brandId.equals(brand.getId())){22                     map.put("品牌", brand.getName());23                     break;24                 }25             }26         }27         //价格 0-99 1600以上28         if(null != price){29             String[] split = price.split("-");30             //如果切割后的长度等于2 就说明这是一个价格区间31             if(split.length == 2){32                 map.put("价格", price);33             }else {34                 map.put("价格", price + "以上");35             }36         }37         model.addAttribute("map", map);38         39         Pagination pagination = searchService.selectPaginationFromSolr(pageNo, keyword, price, brandId);40         model.addAttribute("pagination", pagination);41         model.addAttribute("keyword", keyword);42         model.addAttribute("price", price);43         model.addAttribute("brandId", brandId);44         45         return "search";46     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

提示: 这里使用到了SolrService, 相信看我以前博文的朋友都知道这个地方还需要配置dubbo, 就是服务提供方和适用方, 这里为了简便直接略过, 实际开发中是必须要配置的, 否则就调用不了SolrService中的方法了.

这个controller 中往search.jsp中put了很多东西, 具体这些东西什么用我们可以先不管, 我们先看下search.jsp页面.

而且这个controller中查询brand 是从redis中查询出来的, 我们会在下面讲到这个.

48304ba5e6f9fe08f3fa1abda7d326ab.png1  2             

 3                  已选条件: 4                      5                           6                             ${m.key }:${m.value } 7                          8                      9             
10             

48304ba5e6f9fe08f3fa1abda7d326ab.png

上面这个地方就是为何要在controller设置map值了, 这个是显示已选择的过滤条件.

48304ba5e6f9fe08f3fa1abda7d326ab.png1  2 

 3     
 4         
品牌:
 5         
 6             
 7                 
  •  8                  9                     
  • 10                         ${brand.name }11                     12                 13                 
14             
15         
16     
17 
18 19 20 
21     
22         
价格:
23         
24             
25                 
  • 26                     
  • 27                         0-9928                     29                     
  • 30                         100-29931                     32                     
  • 33                         300-59934                     35                     
  • 36                         600-99937                     38                     
  • 39                         1000-159940                     41                     
  • 42                         1600以上43                     44                 
45             
46         
47     
48 
49 

48304ba5e6f9fe08f3fa1abda7d326ab.png

接下来我们来看下对应的js方法:

48304ba5e6f9fe08f3fa1abda7d326ab.png

48304ba5e6f9fe08f3fa1abda7d326ab.png

这个就可以实现 添加 过滤条件的选项了.

三, 使用Redis 取出商品品牌列表

首先 当我们在后台添加或者修改品牌时, 我们应该同样将这个品牌添加到Redis中, 格式类似于: {"brandId":"brandName"}

controller层:(当我们在后台添加或者修改品牌)

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired 2     private Jedis jedis; 3     //修改 4     public void updateBrandById(Brand brand){ 5         //保存或修改 时修改Redis中的品牌, hmset适合批量添加品牌 6         /*Map map = new HashMap(); 7         map.put(String.valueOf(brand.getId()), brand.getName()); 8         jedis.hmset("brand", map);*/ 9         jedis.hset("brand", String.valueOf(brand.getId()), brand.getName());10         brandDao.updateBrandById(brand);11     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

redis中有了品牌列表后, 然后就是查询了:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired 2     private Jedis jedis; 3     //查询Redis中的品牌结果集 4     public List selectBrandListFromRedis(){ 5         List brands = new ArrayList(); 6         Map hgetAll = jedis.hgetAll("brand"); 7         Set> entrySet = hgetAll.entrySet(); 8         for (Entry entry : entrySet) { 9             Brand brand = new Brand();10             brand.setId(Long.parseLong(entry.getKey()));11             brand.setName(entry.getValue());12             brands.add(brand);13         }14         15         return brands;16     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

到了这里redis查询brand就完成了, 那么继续看下关于solr 是如何加入过滤条件的吧:

48304ba5e6f9fe08f3fa1abda7d326ab.png1 @Autowired  2     private SolrServer solrServer;  3     //查询商品信息从Solr  4     public Pagination selectPaginationFromSolr(Integer pageNo, String keyword, String price, Long brandId){  5         ProductQuery productQuery = new ProductQuery();  6         //当前页  7         productQuery.setPageNo(Pagination.cpn(pageNo));  8         //每页数  9         productQuery.setPageSize(8); 10          11         SolrQuery solrQuery = new SolrQuery(); 12         //关键词 商品名称 13         solrQuery.set("q", "name_ik:"+keyword); 14         //回显数据 15         StringBuilder params = new StringBuilder(); 16         params.append("keyword=").append(keyword); 17          18         //排序 19         solrQuery.addSort("price", ORDER.asc); 20          21         //高亮 22         //1,设置, 打开高亮的开关 23         solrQuery.setHighlight(true); 24         //2, 设置高亮字段 25         solrQuery.addHighlightField("name_ik"); 26         //3, 设置关键字高亮的样式 2016 27         //设置前缀和后缀 28         solrQuery.setHighlightSimplePre(""); 29         solrQuery.setHighlightSimplePost(""); 30          31         //过滤条件 品牌 32         if(null != brandId){ 33             solrQuery.addFilterQuery("brandId:"+brandId); 34             params.append("&brandId=").append(brandId); 35         } 36         //过滤价格 0-99  1600 37         if(null != price){ 38             String[] split = price.split("-"); 39             //如果切割后的长度等于2 就说明这是一个价格区间 40             if(split.length == 2){ 41                 solrQuery.addFilterQuery("price:["+split[0]+" TO "+split[1]+"]"); 42             }else { 43                 solrQuery.addFilterQuery("price:["+split[0]+" TO *]"); 44             } 45             params.append("&price=").append(price); 46         } 47          48         //分页  limit 开始行,每页数 49         solrQuery.setStart(productQuery.getStartRow()); 50         solrQuery.setRows(productQuery.getPageSize()); 51          52         QueryResponse response = null; 53         try { 54             response = solrServer.query(solrQuery); 55              56         } catch (Exception e) { 57             e.printStackTrace(); 58         } 59         //分析这个Map 60         //第一层Map: Key String == ID : Value: Map 61         //第二层Map: Key String == name_ik : Value: List 62         //获取到List: String 0,1,2.... 63         Map>> highlighting = response.getHighlighting(); 64          65          66         List products = new ArrayList(); 67         //结果集 68         SolrDocumentList docs = response.getResults(); 69         //总条数 70         long numFound = docs.getNumFound(); 71         for (SolrDocument doc : docs) { 72             Product product = new Product(); 73             //商品的ID 74             String id = (String)doc.get("id"); 75             product.setId(Long.parseLong(id)); 76              77             //取第二层Map 78             Map> map = highlighting.get(id); 79             //取List集合 80             List list = map.get("name_ik"); 81              82             //商品名称 83             //String name = (String)doc.get("name_ik"); 84             //product.setName(name); 85             product.setName(list.get(0)); //list.get(0) 中的name是已经设置为高亮的 86              87             //图片 88             String url = (String)doc.get("url"); 89             product.setImgUrl(url); 90             //价格 这里的价格本身是保存在bbs_sku表中的, 而我们在这里将price属性直接添加到了Product中 91             //因为我们在做上架的时候, 查询的是bbs_sku中price最小的值 然后保存到solr中的, 所以这里我们就直接将price属性添加到product中了 92             //这里的价格只有一个值 93             //Float price = (Float)doc.get("price"); 94             product.setPrice((Float)doc.get("price")); 95             //品牌ID 96             //Integer brandId = (Integer)doc.get("brandId"); 97             product.setBrandId(Long.parseLong(String.valueOf((Integer)doc.get("brandId")))); 98             products.add(product); 99         }100         101         Pagination pagination = new Pagination(102                     productQuery.getPageNo(),103                     productQuery.getPageSize(),104                     (int)numFound,105                     products106                 );107         //页面展示108         String url = "/search";109         pagination.pageView(url, params.toString());110         111         return pagination;112     }

48304ba5e6f9fe08f3fa1abda7d326ab.png

这个就是本博文的重中之重了, code上面都加了注释, 相信还是比较容易理解的.

5f37628559badc978b16f0236e792138.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值