solr进阶八:jQuery UI Autocomplete与solr搜索结合

来源:互联网 发布:linux下部署禅道 编辑:程序博客网 时间:2024/05/22 14:52

大致的流程:

页面捕获到文字 --> 传到servletController)层,servlet层调用后台 --> 后台根据servlet层传来的参数进行动态从solr中获取数据 --> solr 数据返回到servlet层,解析 --> 展现到页面上。

 

solr里面新建一个core,在MySQL数据库里面新建一个表,从这个表导入数据到solrcore中,具体步骤可以上网查或者看我前面的教程。

SQL语句:


SET FOREIGN_KEY_CHECKS=0;-- ------------------------------ Table structure for lifeixroles-- ----------------------------DROP TABLE IF EXISTS `lifeixroles`;CREATE TABLE `lifeixroles` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `accountId` int(11) DEFAULT NULL,  `level` int(11) DEFAULT NULL,  `name` varchar(255) DEFAULT NULL,  `accountName` varchar(255) DEFAULT NULL,  `namePinyin` varchar(255) DEFAULT NULL,  `l99NO` int(11) DEFAULT NULL,  `photoPath` varchar(255) DEFAULT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;-- ------------------------------ Records of lifeixroles-- ----------------------------INSERT INTO `lifeixroles` VALUES ('1', '4', '38', '崭露头脚', 'peter', 'peter', '150104', '02/MjAwOTAzMjgyMTM1NTdfMjIwLjI0OS43OS4zNV8zMzM2MDI=.jpg');INSERT INTO `lifeixroles` VALUES ('2', '8', '1', '小虾米', '立方咖啡', 'lifangkafei', '150108', '20/MjAwOTAyMTYwMzQxMjBfMjIwLjI0OS43OS4zNV82MDYwNTc=..JPG');INSERT INTO `lifeixroles` VALUES ('3', '11', '46', '名动江湖', 'nick', 'nick', '150121', '10/MjAxNDA2MTMxMTQ2MDVfMTkyLjE2OC4xOTkuNTdfNTA0NDcy.jpg');INSERT INTO `lifeixroles` VALUES ('4', '10', '1', '小虾米', 'oz', 'oz', '150130', '21/MjAxMjEyMjExNTA5MzlfMTgzLjM3LjM0LjI5XzIzMjA1Nw==.png');INSERT INTO `lifeixroles` VALUES ('5', '49', '46', '李四', '立方方圆', 'li', '150163', '10/MjAwOTAyMDcxMjQwMzBfMjIwLjI0OS43OS4zNV83MjQ3ODI=..jpg');

schema.xml的部分配置参考:

分词器:

指定数据库配置文件:

由于新建core是拷贝solr-4.10.2\example\multicore这里面的core,所以配置文件非常简单。在自己的core里面看看分词器是否有用,结果显示是有用的:

可是到搜索里面搜索指定字段的部分词语时,搜索不出,只能搜索出全名的:

查找故障很久都找不出为什么,包括把multiValued改为true,虽然不知道具体原因,但是改了这个,但是没有用,显示出的结果带方括号而已。

后来把这些数据导入collection1就正常了,可能是一些关键的东西没有配置,因为原来core里面的配置是最简单的基础配置,这有待于后面的仔细研究学习。搜索出关键词的数据:

这样就好办了,开始编码!

后台还是servletjsonjar包生成json数据返回到前台页面,具体步骤可以看我前面的总结教程。

对象转换成json语句的工具类:src\com\lifeix\util\FastJsonUtil.java

package com.lifeix.util;import com.alibaba.fastjson.JSON;/** * Created by lhx on 14-12-10 下午4:15 * * @project jspProject * @package com.lifeix.util * @blog http://blog.csdn.net/u011439289 * @email 888xin@sina.com * @Description */public class FastJsonUtil {    /**     * Object实体转换为json     * @param object     * @return     */    public static String object2json(Object object){        JSON json = (JSON) JSON.toJSON(object);        return json.toJSONString();    }}

后台从solr服务器上获取数据的处理类:\src\com\lifeix\util\SolrGetFtTopic2.java

package com.lifeix.util;import org.apache.solr.client.solrj.SolrServer;import org.apache.solr.client.solrj.SolrServerException;import org.apache.solr.client.solrj.impl.HttpSolrServer;import org.apache.solr.client.solrj.response.QueryResponse;import org.apache.solr.common.SolrDocument;import org.apache.solr.common.SolrDocumentList;import org.apache.solr.common.params.ModifiableSolrParams;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * Created by lhx on 14-12-9 上午10:30 * * @project jspProject * @package com.lifeix.util * @blog http://blog.csdn.net/u011439289 * @email 888xin@sina.com * @Description */public class SolrGetFtTopic2 {    private static final String SOLR_URL = "http://localhost:8080/solr/collection1";    public String queryAll(String htmlWord){        ModifiableSolrParams params = new ModifiableSolrParams();        params.set("q","accountName:"+htmlWord);        params.set("start",0);        params.set("rows",10);        params.set("sort","score desc");        params.set("f1","*,score");        SolrServer server = new HttpSolrServer(SOLR_URL);        List<Map<String,Object>> listWord = new ArrayList<Map<String, Object>>();        Map<String,Object> map = null ;        try {            QueryResponse response = server.query(params);            SolrDocumentList list = response.getResults();            for (int i = 0; i < list.size(); i++) {                map = new HashMap<String, Object>();                SolrDocument document = list.get(i);                map.put("label",document.getFieldValue("l99NO") );                map.put("value", document.getFieldValue("accountName"));                listWord.add(map);            }            return  FastJsonUtil.object2json(listWord) ;        } catch (SolrServerException e) {            e.printStackTrace();        }        return null ;    }}

Servlet层从前台页面获取输入值,再交给后台处理

\src\com\lifeix\servlet\JsonSolrServlet.java

package com.lifeix.servlet;import com.lifeix.util.SolrGetFtTopic2;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;/** * Created by lhx on 14-12-10 下午5:29 * * @project jspProject * @package ${PACKAGE_NAME} * @blog http://blog.csdn.net/u011439289 * @email 888xin@sina.com * @Description */public class JsonSolrServlet extends HttpServlet {    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        //获取网页上文本框输入的内容        String htmlWord = request.getParameter("term").trim();        String jsonStr = "" ;        SolrGetFtTopic2 solrGetFtTopic = new SolrGetFtTopic2();        if (!"".equals(htmlWord) && htmlWord != null){            //传入参数,根据参数来进行搜索            jsonStr = solrGetFtTopic.queryAll(htmlWord);        }        PrintWriter pw = null;        try {            response.setContentType("application/json; charset=utf-8");            response.setCharacterEncoding("UTF-8");            response.setHeader("Cache-Control", "no-cache");            pw = response.getWriter();            pw.print(jsonStr);            pw.flush();        }catch (Exception e) {            e.printStackTrace();        }        finally {            if (pw != null)                pw.close();        }    }    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        this.doPost(request,response);    }}

现在是前台页面的jQuery UI Autocomplete代码,这些代码可以参考

jQuery UI Autocomplete官网的远端缓存处理例子:

http://jqueryui.com/autocomplete/#remote-with-cache

jQuery UI AutocompletejQuery UI的自动完成组件

 

我的代码如下:

<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Fancy Validate - jQuery UI Autocomplete</title><link href="jquery-ui/css/ui-lightness/jquery-ui-1.8.17.custom.css" rel="stylesheet" /><script src="js/jquery-1.7.1.min.js"></script><script src="jquery-ui/js/jquery-ui-1.8.17.custom.min.js"></script><script src="jquery-ui/js/jquery-ui-widget-combobox.js"></script><style>    body {        font-size: 14px;    }    fieldset {        width: 650px;        margin: 0 auto;        text-align: right;    }    fieldset div {        margin: 15px auto;    }    .cbo .ui-button-text {        line-height: 1.3;        padding-top: 0;        padding-bottom: 0;    }    .cbo .ui-autocomplete-input {        width: 7.2em;    }</style><script>    $(function() {        var cache = {};        $("#username").autocomplete({            minLength: 2,            source:function(request, response){                var term = request.term;                if(term in cache){                    response(cache[term]);                    return ;                }                $.getJSON('jsonsolr',request,function(data,status,xhr){                    cache[term] = data ;                    response(data);                });            }        });        var cache1 = {};        $("#username1").autocomplete({            minLength: 2,            source:function(request, response){                var term = request.term;                if(term in cache1){                    response(cache1[term]);                    return ;                }                $.getJSON('jsonsolr2',request,function(data,status,xhr){                    cache1[term] = data ;                    response(data);                });            }        });        var cache2 = {};        $("#l99NO").autocomplete({            minLength: 6,            source:function(request, response){                var term = request.term;                if(term in cache2){                    response(cache2[term]);                    return ;                }                $.getJSON('jsonsolrl99',request,function(data,status,xhr){                    cache2[term] = data ;                    response(data);                });            }        });        // 自定义source函数        var hosts = ["gmail.com", "live.com", "hotmail.com", "yahoo.com", "cnblogs.com", "火星.com", "囧月.com"];        $("#email1").autocomplete({            autoFocus: true,            source: function(request, response) {                var term = request.term, //request.term为输入的字符串                        ix = term.indexOf("@"),                        name = term, // 用户名                        host = "", // 域名                        result = []; // 结果                result.push(term);                // result.push({ label: term, value: term }); // json格式                if (ix > -1) {                    name = term.slice(0, ix);                    host = term.slice(ix + 1);                }                if (name) {                    var findedHosts = (host ? $.grep(hosts, function(value) {                                return value.indexOf(host) > -1;                            }) : hosts),                            findedResults = $.map(findedHosts, function(value) {                                return name + "@" + value; //返回字符串格式                                // return { label: name + " @ " + value, value: name + "@" + value }; // json格式                            });                    result = result.concat($.makeArray(findedResults));                }                response(result); //呈现结果            }        });        /* combobox autocomplete */        $("#combo1").combobox();    });</script></head><body><form action="?" id="fancyform">    <fieldset>        <legend>jQuery UI Autocomplete</legend>        <div>            根据用户名搜索(输词语,如:立方,提示龙号):<input id="username" type="text" />        </div>        <div>            根据用户名搜索(输词语,如:立方,提示用户名):<input id="username1" type="text" />        </div>        <div>            根据龙号来搜索(输全部,如:150108):<input id="l99NO" type="text" />        </div>        <div>            Email(随便输):<input id="email1" type="text" />        </div>        <div class="cbo">            Combobox(选择):<select id="combo1">            <option value="">请选择</option>            <option value="1">地球</option>            <option value="2">月球</option>            <option value="3">火星</option>        </select>        </div>    </fieldset></form></body></html>

最后的实现效果如下:

——————————————————————————————————————

————————————————————————————————————————


后记:

因为前面改过multiValued的值,改为true了,所以搜索返回的值是带方括号的,导致生成的json语句不是正规的json,所以前台页面解析不了,通过断点调试可以发现这个问题:

另外这个例子还有一个缺点,就是中文输入的话,输入词语不能马上触发事件,要接着敲键盘或者敲一个空格键,jQuery才会把文本中的文字送到后台处理,而英文和数字没有这个问题,这个还要处理!



资料下载:http://pan.baidu.com/s/1jG1gAHK

 

20141212日 补

 

今天上午调试了以下jQuery UI Autocomplete代码,改为以下的模样:

界面输入的时候,还是要多按一个字符才能与后台交互。仔细一看,在汉字没有输入的前提下,就有了一个小下划线:

当设置minLength: 0时,此时就开始触发了,输入完后默认已经触发过一次,不会触发,再在键盘上按多一个键,我按了空格,结果就能把按键之前的文本发送到后台了。

可是,当你用其他浏览器的时候,居然没有这个现象,输入中文的时候,文本框没有小划线。

这是chrome浏览器的:

这是IE11的效果

原来这是jQuery UI Autocomplete在火狐狸上的一个bug

上网找了一下,真的有解决的方法啊!

参考:修复jQuery UI AutocompleteFF中不支持中文的BUG

我的是在jquery-ui-1.8.17.custom.min.js这个文件里改,搜索:blur.autocomplete

127行,原代码格式有点难看,格式化一下代码:

然后变成:

再在此处加上:

.bind("input.autocomplete",function(){            b.search(self.item);        })

刷新一下火狐狸,输入词语,马上就与后台交互了:


0 0
原创粉丝点击