使用 LayUI+SpringBoot+Solr 模仿百度一下搜索引擎

前言

全文检索sql 模糊查询,最大的区别,在于
① 前者能将要查询的关键字符串先进行灵活分词,再进行匹配
② 后者只会直接死板匹配
③ 很多网站都有站内搜索,每个后台的应该会,故做了个 demo 分享

还有很多优点,相信大家都已经了解

摘要

前后端分离

① 前端框架:jQuery、LayUI

② 后台框架:SpringBoot、Solr

模仿百度搜索,麻雀虽小,五脏俱全

本文很多基础都来自笔者之前的文章
① Solr 基础:[增删改查] SpringBoot 整合 Solr 之 SolrClient 实现 CRUD、分页接口、高亮显示
② 前后端分离之跨域问题解决:在 SpringBoot 中设置允许跨域请求
③ LayUI 基础:使用新、热、轻量、简单、强大、优美的 LayUI框架 构建前端页面

效果

gif 图解读:

① 搜索 Java爬虫技术
② 搜索 SpringBoot整合Solr
③ 随便点击搜索结果的一个链接

这里写图片描述

思考:

若不是使用了 Solr全文检索,则搜索词 Java学习,因首字母大写、后面还有中文,无法匹配 java爬虫 等。

前端代码

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>ITAEM 搜索</title>
        <link rel="stylesheet" href="layui/css/layui.css" />
        <script src="js/jquery-1.7.2.js"></script>
        <script src="layui/layui.js"></script>
        <script type="text/javascript">
        </script>
    </head>

    <body>
        <br />
        <div class="layui-row layui-col-space3">
            <div class="layui-col-md1">
                <img src="img/itaem.png" height="30px" />
            </div>
            <div class="layui-col-md2">
                <input type="text" id="query" name="q" required lay-verify="required" placeholder="输入关键字" class="layui-input">
            </div>
            <div class="layui-col-md1">
                <button id="btn2" onclick="upd()" class="layui-btn"> 搜索  </button>
            </div>
        </div>
        <!--横线-->
        <hr class="layui-bg-red">

        <!--搜索结果-->
        <div id="result">
            <hr class="layui-bg-gray">
        </div>
        <div id="page"></div>

        <script>
            function show(highlight, href) {
                //由于为Java集合 的 List 类型、 Array 类型共存,只能这样
                var i = 0;
                $.each(highlight, function(index, title) {
                    var a = $("<a></a>").append(title.title[0]).attr("href", href[i].href[0]);
                    a.attr("target", "_blank");
                    var bq = $("<blockquote class='layui-elem-quote'>").append(a);
                    var div = $("<div></div>").append(bq);
                    $('#result').append("<hr />").append(div)
                    i++;
                });
            }

            function upd() {
                var q = $("#query").val();
                $.ajax({
                    type: "get",
                    url: "http://localhost/test/select/" + q + "/0/5",
                    success: function(result) {
                        $('#result').empty()
                        var highlight = result.highlight;
                        var href = result.href;
                        var total = result.total;
                        show(highlight, href);
                        //分页条再次渲染
                        layui.use('laypage', function() {
                            //获取页模块
                            var laypage = layui.laypage;
                            //执行一个laypage实例
                            laypage.render({
                                //注意,这里的 page 是 ID,不用加 # 号
                                elem: 'page',
                                //数据总数,从服务端得到
                                count: total,
                                //每页的数据量
                                limit: 5,
                                //相连页数量
                                groups: 5
                            });
                        });

                    }
                });
            }
        </script>
    </body>

</html>

后台

package com.cun.controller;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * 优化:抽取 Id、text 为一个 JavaBean
 * @author linhongcun
 *
 */
@RestController
@RequestMapping("/test")
@EnableSwagger2
public class SolrController {

    @Autowired
    private SolrClient client;

    /**
     * 1、增
     * @param message
     * @return
     * @throws IOException
     * @throws SolrServerException
     */
    @PostMapping("/insert")
    public String insert(String title, String href) throws IOException, SolrServerException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
        String dateString = sdf.format(new Date());
        try {
            SolrInputDocument doc = new SolrInputDocument();
            doc.setField("id", dateString);
            doc.setField("title", title);
            doc.setField("href", href);
            /*
             * 如果 spring.data.solr.host 里面配置到 core了, 那么这里就不需要传 collection1 这个参数 下面都是一样的 即
             * client.commit();
             */

            client.add("itaem", doc);
            client.commit("itaem");
            return dateString;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "error";
    }

    /**
     * 4、删 all
     * @return
     */
    @DeleteMapping("deleteAll")
    public String deleteAll() {
        try {

            client.deleteByQuery("itaem", "*:*");
            client.commit("itaem");
            return "success";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "error";
    }

    /**
     * 7、查  ++:关键字、高亮、分页  ✔
     * @return 
     * @return
     * @throws SolrServerException
     * @throws IOException
     */
    @GetMapping("/select/{q}/{page}/{size}")
    public Map<String, Object> select(@PathVariable String q, @PathVariable Integer page, @PathVariable Integer size)
            throws SolrServerException, IOException {
        SolrQuery params = new SolrQuery();

        // 查询条件
        params.set("q", q);

        // 排序,实际应根据得分,不过也没关系,所有查到的记录都是相关的,不相干的排除了
        params.addSort("id", SolrQuery.ORDER.desc);

        // 分页
        params.setStart(page);
        params.setRows(size);

        // 默认域
        params.set("df", "title");

        // 只查询指定域
        params.set("fl", "href");

        // 开启高亮
        params.setHighlight(true);
        // 设置前缀
        params.setHighlightSimplePre("<span style='color:red'>");
        // 设置后缀
        params.setHighlightSimplePost("</span>");

        // solr数据库是 itaem
        QueryResponse queryResponse = client.query("itaem", params);
        SolrDocumentList results = queryResponse.getResults();
        // 数量,分页用
        long total = results.getNumFound();// JS 使用 size=MXA 和 data.length 即可知道长度了(但不合理)

        // 获取高亮显示的结果, 高亮显示的结果和查询结果是分开放的
        Map<String, Map<String, List<String>>> highlight = queryResponse.getHighlighting();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("total", total);
        map.put("href", results);
        map.put("highlight", highlight);
        return map;

    }

}

猜你喜欢

转载自blog.csdn.net/larger5/article/details/79946353