美文网首页
springboot-solr项目练手

springboot-solr项目练手

作者: 就这些吗 | 来源:发表于2020-01-26 04:41 被阅读0次

在浏览本文前希望你已经对solr已有一定的了解,可以参考我的其他文章进行学习
本项目需要额外启动一个solr:如何搭建solr的配置环境
本项目中用到了该文的第二种方法来导入数据:solr数据导入的两种方法
本文写了点在配置时遇到的坑和几个参数的意义:solr中域的作用和坑

如果~~你实在不想配置,没关系,在百度云中我上传了两个版本,solr-7.7.2-jetty是没有配置数据库链接的版本,solr-7.7.2-jetty-connectDB是配置了数据库链接的版本,里面均含有本项目的实体类配置、数据库中的实体类数据,直接启动就能用
链接:https://pan.baidu.com/s/1h2279pQZIDgCMLiP4DREbA
提取码:ziem

项目地址:https://github.com/g992987642/boot-solr
项目展示:

image.png

这里的所有数据都是通过solr查出来的,邮箱的高亮也是通过solr实现(这个高亮确实是天坑)。

注意:solr入门我感觉并不难,但是有不少小坑需要踩,基本也是能通过搜索引擎解决的,但是如何用好确实是一门学问,本项目只是简单入门。

先是用.sql文件创建一个数据库啦,然后修改对应的配置(记得去改哦),.sql文件已经放在项目的doc文件夹中了


image.png

注意,本项目是通过mybatis查询后再添加到solr的方式进行存储的,如果是第一次运行,请在数据库创建完成后,打开框选中的代码行,进行导入,后续运行注释该行即可。


image.png

然后是配置SolrConfig类,与redisTemplate类似,为了注入solrTemplate


image.png

在service的实现类中实现了两种高亮查询的方式,一种是通过solrTemplate(这是Spring
data的封装类,但是如果想实现只对查询字符串高亮而不是整个字段的话,本例中并没有实现),还有一种是通过solrClient自带的查询方式(需要设置的参数比较多,当然也比较自由,实现了一部分准确字符串高亮)
即solrTemplate只实现了 查询qq 得到结果992987642@qq.com (全部高亮)
用solrClient实现了查询qq,得到结果992987642@qq.com(准确字符串高亮)

image.png

注意:在solr中高亮的实现是通过查询所有结果后,再将高亮域进行高亮实现的,所有查询结果与高亮域查询结果存储在不同地方,需要通过高亮域置换所有查询结果中应该高亮的地方,才能实现高亮。

说下下面方法的思路:使用solrClient时,需要配置查询的分页和高亮域,得到所有域的信息和高亮域的信息(注意,这两个域是分开查询出来的),例如查询结果为[{id: "123", field: "<em>xxx</em>"}],被<em></em>修饰的xxx就是高亮部分,需要通过未高亮的域的值替换为高亮的值来实现。

 private ResponseCode solrQuerySearch(String keyword, Integer current, Integer rows) {
        if (StringUtils.isEmpty(keyword)) {
            return new ResponseCode("请输入查询内容");
        }
        if (current == 1) {
            current = 0;
        } else {
            current = (current - 1) * rows;
        }
        SolrQuery query = new SolrQuery();
        query.setStart(current);
        query.setRows(rows);
        query.set("wt", "json");
        try {
            String[] fields = {"item_username", "item_email", "item_qq", "item_password"}; //设置solr中定义的域

            //高亮配置
            String[] lightNames = {"item_username", "item_email", "item_qq"}; //设置需要高亮的域
            //这里对应了solr管理页面中是否高亮的选项
            query.setParam("hl", "true");
            query.setParam("hl.fl", lightNames);
            query.setHighlightSimplePre("<em  style='color: red'>");
            query.setHighlightSimplePost("</em>");

            /**
             * 设置查询关键字的域
             * 一般对应solr中的复制域(<copyFiled>)。
             * 因为用户查询的数据不确定是什么,定义在复制域中的字段,Solr会自动进行多字段查询匹配
             */
            //query.set("q", "keyword:*" + keyword + "*"); //在Solr中查询语句:/select?q=keyword:*xxx*,这种方式也不会让准确字符串高亮
            query.set("q", "keyword:" + keyword );//在Solr中查询语句:/select?q=keyword:xxx,只有这种方式才能准确字符串高亮
            QueryResponse response = solrClient.query(query);
            //获取被高亮的数据集合,其中的数据结构类似:[{id: "123", field: "<em>xxx</em>"}]
            Map<String, Map<String, List<String>>> highlighting = response.getHighlighting();
            SolrDocumentList documents = response.getResults(); //获取匹配结果
            long numFound = documents.getNumFound(); //获取匹配的数据个数
            if (numFound != 0) {
                List<Object> entityList = new ArrayList<>();
                for (SolrDocument document : documents) {
                    //documents中存放了匹配的所有数据(未高亮),而highlighting中存放了高亮匹配的数据(高亮)
                    //通过id主键获取到id值,在highlighting中通过id值获取对应的高亮数据
                    Map<String, List<String>> listMap = highlighting.get(document.getFieldValue("id").toString());
                    for (int i = 0; i < lightNames.length; i++) {
                        if (listMap.get(lightNames[i]) != null) {
                            //根据设置的高亮域,将documents中未高亮的域的值替换为高亮的值
                            document.setField(lightNames[i], listMap.get(lightNames[i]).get(0));
                        }
                    }
                    Map<String, Object> fieldMap = new HashMap<>();
                    for (int i = 0; i < fields.length; i++) {
                        //前端需要的是实体类的名称email,不是solr里的item_email
                        fieldMap.put(fields[i].split("_")[1], String.valueOf(document.getFieldValue(fields[i])));
                    }
                    entityList.add(fieldMap);
                }
                return new ResponseCode(entityList, numFound);
            } else {
                return new ResponseCode("未搜索到任何结果");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseCode("服务器异常");
        }
    }

    private ResponseCode solrTemplateSearch(String keyword, Integer current, Integer rows) {
        //高亮配置
        HighlightQuery query = new SimpleHighlightQuery();
        String[] fieldNames = {"item_username", "item_email", "item_qq"};
        HighlightOptions highlightOptions = new HighlightOptions().addField(fieldNames); //设置高亮域
        highlightOptions.setSimplePrefix("<em style='color: red'>"); //设置高亮前缀
        highlightOptions.setSimplePostfix("</em>"); //设置高亮后缀
        query.setHighlightOptions(highlightOptions); //设置高亮选项

        if ("".equals(keyword)) {
            return new ResponseCode("请输入查询内容");
        }

        try {
            /**
             * 通过Criteria构建查询过滤条件
             * 其中这里的`keyword`等价于solr core中schema.xml配置的域,且`keyword`是复制域名
             * 因为查询的内容是不确定的,solr提供了复制域实现同时查询多个域中的数据,并返回匹配的结果
             */
            Criteria criteria = new Criteria("keyword");
            //按照关键字查询
            if (keyword != null && !"".equals(keyword)) {
                criteria.contains(keyword);
            }
            query.addCriteria(criteria);

            if (current == null) {
                current = 1; //默认第一页
            }
            if (rows == null) {
                rows = 20; //默认每次查询20条记录
            }
            query.setOffset((long) ((current - 1) * rows)); //从第几条记录开始查询:= 当前页 * 每页的记录数
            query.setRows(rows);
            //
            HighlightPage<Search> page = solrTemplate.queryForHighlightPage("", query, Search.class);
           // 循环高亮入口集合
            for (HighlightEntry<Search> h : page.getHighlighted()) {
                Search search = h.getEntity(); //获取原实体类
                if (h.getHighlights().size() > 0) {
                    h.getHighlights().forEach(light -> {
                        if (search.getUsername().contains(keyword)) {
                            search.setUsername(light.getSnipplets().get(0));
                        }
                        if (search.getEmail().contains(keyword)) {
                            search.setEmail(light.getSnipplets().get(0));
                        }
                        if (search.getQq().contains(keyword)) {
                            search.setQq(light.getSnipplets().get(0));
                        }
                    });
                }
            }
            return new ResponseCode(page.getContent(), page.getTotalElements());
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseCode("查询失败");
        }
    }

相关文章

网友评论

      本文标题:springboot-solr项目练手

      本文链接:https://www.haomeiwen.com/subject/jurcthtx.html