solr7实现搜索框的自动提示并统计词频

1:用solr 的suggest组件,统计词频相对麻烦。

2:用TermsComponent,自带词频统计功能。

Terms组件提供访问索引项的字段和每个词相匹配的文档数量,类似于关系型数据库的like模糊查询(keywords like "手机%"),然后统计数量返回给前端,但这样有一个问题。如果该字段非词性的。精确性和效率性不高。

solr中TermsComponent组件完美的解决了这么一个方案,能够统计指定搜索域中所有词的信息。类似于lucene Term查询。

刚研究了会solrj的TermsComponent :http://wiki.apache.org/solr/TermsComponent

solrconfig配置如下:

这通常是一个默认的配置,一般使用不需要进行配置,除非你有更高的需求。

返回结果:默认按词的count出现次数倒序排序。

相关参数说明:

    terms={true|false} -必须的. 打开 TermsComponent组件
terms.fl={FIELD NAME} - 必须的. terms的名称field,可以指定多个如:terms.fl = field1&terms.fl = field2……
terms.lower={term下限} - 可选的. 这个term开始。如果不指定,使用空字符串,这意味着从头开始的。
terms.lower.incl={true|false} - 可选的. 包括下限的结果集。默认是true。

terms.mincount=<Integer> - 可选的. 最小文档频率返回被包含的. 结果包含最小统计数量(例如 >= 最小统计数量)
terms.maxcount=<Integer> - 可选的. 最大文档频率. 默认是 -1 ~ 没有上限. 结果包含最大统计数量(例如 <= 最大统计数量)
terms.prefix={String} - 可选的. 限制匹配terms从前缀开始。
terms.regex={String} - 可选的. 限制条件匹配terms的正则表达式匹配。<!> Solr3.1
terms.regex.flag={case_insensitive|comments|multiline|literal|dotall|unicode_case|canon_eq|unix_lines} - 可选的. Flags to be used when evaluating the regular expression defined in the "terms.regex" parameter (see http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html#compile%28java.lang.String,%20int%29 fore more details). This parameter can be defined multiple times (each time with different flag) <!> Solr3.1
terms.limit={Integer} - 可选的. 返回的最大的terms数量. 默认是 . 如果 < , 那么包含所有的 terms.
terms.upper={term上限} - 可选的. The term to stop at. Either upper or terms.limit must be set.
terms.upper.incl={true|false} -可选的. 包括上限的结果集。默认是false。
terms.raw={true|false} - 可选的. 如果是 true, return the raw characters of the indexed term, regardless of if it is human readable. For instance, the indexed form of numeric numbers is not human readable. The default is false.
terms.sort={count|index} - 可选的. 如果count,各种各样的terms的频率(最高计数第一)。如果index,索引顺序返回的terms。默认是count。   输出是一个term及其文档频率值的列表。   注:如terms={true|false},{}里的内容蓝色的真实要填写的内容,黑色是描述。

solr7 之 termsComment 官网的demo:

     /**
* terms词频统计测试
*/
@Test
public void TestTerms() throws Exception{
//[1]获取连接
HttpSolrClient client = Constant.getSolrClient();
//[2]创建SolrQuery
SolrQuery query = new SolrQuery();
//[3]设置参数
query.setRequestHandler("/terms");//设置requestHandler
query.setTerms(true);//开启terms
query.setTermsLimit();//设置每页返回的条目数量
query.setTermsLower("家");// 可选的. 这个term开始。如果不指定,使用空字符串,这意味着从头开始的。
query.setTermsPrefix("家");//可选的. 限制匹配,设置terms前缀是以什么开始的。
query.addTermsField("p_name");//必须的. 统计的字段
query.setTermsMinCount();//可选的. 设置最小统计个数
//[4]创建QueryRequest 获取 TermsResponse
QueryRequest request = new QueryRequest(query);
QueryResponse process = request.process(client);
TermsResponse termsResponse = process.getTermsResponse();
//[5]遍历结果
List<Term> terms = termsResponse.getTerms("p_name");
for (Term term : terms) {
System.out.println(term.getTerm() + ":\t"+ term.getFrequency());
}
}

查询的结果:

SolrQuery的父类方法set设置参数的方式统计词频 demo2:

     /**
* terms词频统计测试2
* @throws Exception
*/
@Test
public void TestTerms2() throws Exception{
//[1]实例化HttpSolrClient,以获取与HttpSolrClient的连接
HttpSolrClient client = Constant.getSolrClient();
//[2]创建SolrQuery
SolrQuery query = new SolrQuery();
//[3]设置查询参数
query.set("q", "*:*");
query.set("qt","/terms");//设置requestHandler // parameters settings for terms requesthandler
// 参考 http://wiki.apache.org/solr/termscomponent
query.set("terms","true");//开启terms
query.set("terms.fl", "p_name");//必须的. 统计的字段 //指定下限
// query.set("terms.lower", ""); // term lower bounder开始的字符 ,// 可选的. 这个term开始。如果不指定,使用空字符串,这意味着从头开始的。
// query.set("terms.lower.incl", "true");
// query.set("terms.mincount", "1");//可选的. 设置最小统计个数
// query.set("terms.maxcount", "100"); //可选的. 设置最大统计个数 //http://localhost:8983/solr/terms?terms.fl=text&terms.prefix=家//
//using for auto-completing //自动完成
//query.set("terms.prefix", "家");//可选的. 限制匹配,设置terms前缀是以什么开始的。
query.set("terms.regex", "家+.*");
query.set("terms.regex.flag", "case_insensitive"); //query.set("terms.limit", "20"); //设置每页返回的条目数量
//query.set("terms.upper", ""); //结束的字符
//query.set("terms.upper.incl", "false");
//query.set("terms.raw", "true"); query.set("terms.sort", "count");//terms.sort={count|index} -如果count,各种各样的条款术语的频率(最高计数第一)。 如果index,索引顺序返回条款。默认是count // 查询并获取结果
QueryResponse response = client.query(query);
// 获取相关的查询结果
if (response != null) {
TermsResponse termsResponse = response.getTermsResponse();
if (termsResponse != null) {
Map<String, List<TermsResponse.Term>> termsMap = termsResponse.getTermMap();
for (Map.Entry<String, List<TermsResponse.Term>> termsEntry : termsMap.entrySet()) {
//System.out.println("Field Name: " + termsEntry.getKey());
List<TermsResponse.Term> termList = termsEntry.getValue();
for (TermsResponse.Term term : termList) {
System.out.println(term.getTerm() + " : "+ term.getFrequency());
}
}
}
}
}

结果:

整合到工程中去:

1、需要jQuery UI 的自动完成组件(Autocomplete)

2、solr7 的 Terms 组件

①jsp页面:

js引入:

  <link rel="stylesheet" href="resource/js/jquery-ui-1.10.4.custom/css/base/jquery-ui-1.10.4.custom.min.css">
<script src="resource/js/jquery-ui-1.10.4.custom/js/jquery-1.10.2.js"></script>
<script src="resource/js/jquery-ui-1.10.4.custom/development-bundle/ui/jquery.ui.core.js"></script>
<script src="resource/js/jquery-ui-1.10.4.custom/development-bundle/ui/jquery.ui.widget.js"></script>
<script src="resource/js/jquery-ui-1.10.4.custom/development-bundle/ui/jquery.ui.position.js"></script>
<script src="resource/js/jquery-ui-1.10.4.custom/development-bundle/ui/jquery.ui.menu.js"></script>
<script src="resource/js/jquery-ui-1.10.4.custom/development-bundle/ui/jquery.ui.autocomplete.js"></script>
<script src="resource/js/common/jquery.custom.mycomplete.js"></script> <!-- 自定义扩展小部件autocomplete的js -->

自定义扩展autocomplete功能(jquery.custom.mycomplete.js)

/**
* 扩展autocomplete功能
* 2017-10-10
* @param $
*/
(function($){
$.widget( "custom.mycomplete", $.ui.autocomplete, {
_renderItem: function( ul, item ) {
//alert(item.term)
//alert(item.frequency)
return $( "<li>" )
.attr( "data-value", item.value ) //当条目被选中时插入到输入框中的值。
.append( $("<a>")
//.text( item.label)
.html("<img width='30' src='img/01.png' />" +
//item.label +
item.term +
// " <span>约10000个商品</span>")
"<span style='float: right;padding-right: 5px;'> 约"+item.frequency+"个商品</span>")
)//条目显示的字符串。
.appendTo( ul );//新创建的 <li> 元素必须追加到的 <ul> 元素。
}
});
})(jQuery)

form表单:

<form id="actionForm" action="serch.do" method="POST">
<div class="form">
<input type="text" class="text" accesskey="s" name="queryString" id="key" value="${queryString }"
autocomplete="off" onkeydown="javascript:if(event.keyCode==13) {query()}">
<input type="button" value="搜索" class="button" onclick="query()">
</div>
<input type="hidden" name="catalog_name" id="catalog_name" value="${catalog_name }"/>
<input type="hidden" name="price" id="price" value="${price }"/>
<input type="hidden" name="page" id="page" value="${page }"/>
<input type="hidden" name="sort" id="sort" value="${sort }"/>
</form>

②JQuery代码:

  对输入内容的动态自动建议并统计词频:

<script type="text/javascript">
$(function() {
$("#key").mycomplete({
minLength: ,//执行搜索前用户必须输入的最小字符数
delay: , //按键和执行搜索之间的延迟,以毫秒计
autoFocus: true,//如果设置为 true,当菜单显示时,第一个条目将自动获得焦点。
source: function(req,resp) {
$.getJSON("serchTerms.do?term="+req.term,resp);
},
response: function( event, ui ) {//在搜索完成后菜单显示前触发
//alert('response')
//alert(ui.content[0].value)
//...
},
select: function( event, ui ) { //当从菜单中选择条目时触发
//alert('select')
//alert(ui.item.term)
//...
$(this).val(ui.item.term);
return false;
},
focus: function( event, ui ) {//当焦点移动到一个条目上(未选择)时触发
//alert('focus')
//...
$(this).val(ui.item.term);
return false;
},
change: function( event, ui ) {//如果输入域的值改变则触发该事件
//alert('change')
//...
},
search: function( event, ui ) {//在搜索执行前满足minLength 和 delay 后触发
//alert('search')
//...
}
});
});
</script>

③提交表单:

<script type="text/javascript">
function query() {
//执行关键词查询时清空过滤条件
document.getElementById("catalog_name").value="";
document.getElementById("price").value="";
document.getElementById("page").value="";
//执行查询
queryList();
}
function queryList() {
//提交表单
document.getElementById("actionForm").submit();
}
function filter(key, value) {
document.getElementById(key).value=value;
queryList();
}
function sort() {
var s = document.getElementById("sort").value;
if (s != "") {
s = "";
} else {
s = "";
}
document.getElementById("sort").value = s;
queryList();
}
function changePage(p) {
var curpage = Number(document.getElementById("page").value);
curpage = curpage + p;
document.getElementById("page").value = curpage;
queryList();
}
</script>

④Controller层:

    /**
* 词频统计查询数据
* @return
* @throws Exception
*/
@RequestMapping("/serchTerms.do")
public String serchTerms() throws Exception{
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
HttpServletResponse response = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getResponse();
String keywords = request.getParameter("term");
String serchTerms = productService.serchTerms(keywords);
System.out.println(serchTerms);
JsonUtil.writeJson2Page(serchTerms, response);
return "product_list";
}

⑤Service层:

//关键字建议词频统计查询
@Override
public String serchTerms(String keywords) throws Exception {
String serchGroupSum = SuggestUtils.getSerchTerms(keywords);
return serchGroupSum;
}

⑥SuggestUtils工具类:

  /**
* 词频统计查询
* @param keywords
* @return
* @throws SolrServerException
*/
public static String getSerchTerms(String keywords) throws Exception {
HttpSolrClient solrServer = Constant.getSolrClient();
// 创建查询参数以及设定的查询参数
SolrQuery query = new SolrQuery();
query.set("q", "*:*");
query.set("qt", "/terms");
query.set("terms", "true");
query.set("terms.fl", "p_name");
//tomcat8之前默认是ISO8859-1,tomcat8及以后,是UTF-8,自己百度一下解决办法
     //推荐学习地址: https://www.w3cschool.cn/regexp/tfua1pq5.html
query.set("terms.regex", keywords+"+.*");
query.set("terms.regex.flag", "case_insensitive");
query.set("terms.sort", "count");//terms.sort={count|index} -如果count,各种各样的条款术语的频率(最高计数第一)。 如果index,索引顺序返回条款。默认是count
// 查询并获取相应的结果!
QueryResponse response = solrServer.query(query);
// 获取相关的查询结果
List<TermsResponse.Term> termList=null;
if (response != null) {
TermsResponse termsResponse = response.getTermsResponse();
if (termsResponse != null) {
Map<String, List<TermsResponse.Term>> termsMap = termsResponse.getTermMap();
for (Map.Entry<String, List<TermsResponse.Term>> termsEntry : termsMap.entrySet()) {
// System.out.println("Field Name: " + termsEntry.getKey());
termList = termsEntry.getValue();
for (TermsResponse.Term term : termList) {
System.out.println(term.getTerm() + " : "+ term.getFrequency());
}
}
}
}
JSONArray array = JSONArray.fromObject(termList);
String jsonstr = array.toString();
return jsonstr;
}

效果如图:

随便选择一个进行搜索,比如选择‘’家系‘’:

结果确实只有三条数据。

刚才用的p_name,现在改为p_keywords,可以看到查询的内容和条数比刚才多了许多。

 query.set("terms.fl", "p_keywords");  

基本功能已经完成,还有待优化,比如:

1、写了十个关键字,删除了一个字也应该建议出下拉的内容(京东是无论你删除前边的关键字还是后边的关键字都能建议出内容)。

2、获取焦点事件,输入框中如果有内容,当再次获取焦点时,同样能获取建议的内容。

(八)solr7实现搜索框的自动提示并统计词频的更多相关文章

  1. jquery+php实现用户输入搜索内容时自动提示

    index.html <html> <head>     <meta charset=;} #search_auto li a:hover{background:#D8D ...

  2. Ajax跨域:Jsonp实例--百度搜索框下拉提示

    Ajax跨域:Jsonp实例--百度搜索框下拉提示 一.总结 一句话总结:a.找好接口:b.用script标签的src引入文件(json数据):c.定义及实现上一步引入文件中的函数 1.如何找到一个网 ...

  3. typecho博客组插件:openSug.js百度搜索框下拉提示免费代码

      Typecho候选搜索增强插件:安装openSug插件即可获得带有“搜索框提示”功能的搜索框,让Typecho搜索更便捷! 支持百度.谷歌.雅虎.Yandex.360好搜.UC神马.酷狗.优酷.淘 ...

  4. 搜索框下面显示提示数据(数据是ajax读取)

    1.前台页面 <div style="margin: 0 auto"> <input type="text" id="wenxian ...

  5. 使用DWR实现自动补全 类似百度搜索框的自动显示效果

    使用DWR实现自动补全 自动补全:是指用户在文本框中输入前几个字母或汉字的时候,自动在存放数据的文件或数据库中将所有以这些字母或汉字开头的数据提示给用户供用户选择 在日常上网过程中,我们经常使用搜索引 ...

  6. UISearchController 的用法[点击搜索框,自动到顶部]

    //在ViewDidLoad里面如下代码 self.searchViewController = [[UISearchController alloc]initWithSearchResultsCon ...

  7. win10 搜索框输入没提示

    1.点击win, 手动在应用里找到Cortana(小娜) 2. 点右键->更多->应用设置,进入到下面的界面 3. 下拉到最下面,找到“重置”即可

  8. DataList:HTML5中的input输入框自动提示宝器

    DataList的作用是在你往input输入框里输入信息时,根据你敲进去的字母,自动显示一个提示下列列表,很像百度或谷歌的搜索框的自动提示,在飞机票火车票的搜索页面上也有这样的效果.它是HTML5里新 ...

  9. Jquery 搜索框自动提示

    为文本框增加自动提示下拉功能,比如输入 1,则从后台数据库查询出包含1 的字段,在文本框增加下拉列表供用户选择 ajax 返回数据为搜索查询字段的json集合 <script src=" ...

随机推荐

  1. kyeremal-bzoj2038-[2009国家集训队]-小z的袜子(hose)-莫队算法

    id=2038">bzoj2038-[2009国家集训队]-小z的袜子(hose) F.A.Qs Home Discuss ProblemSet Status Ranklist Con ...

  2. LeetCode题目:Spiral Matrix II

    原题地址:https://leetcode.com/problems/spiral-matrix-ii/ class Solution { public: vector<vector<in ...

  3. linux c 获取网卡状态(UP or DOWN)

    源代码例如以下: #include <sys/socket.h> #include <sys/ioctl.h> #include <linux/if.h> #inc ...

  4. 网页中多一些常见效果之伸缩菜单(主要是学习js的书写方法)

    效果如下图: 代码很简单,如下: <!doctype html> <html lang="en"> <head> <meta charse ...

  5. 自己动手开发更好用的markdown编辑器-07(扩展语法)

    这里文章都是从个人的github博客直接复制过来的,排版可能有点乱. 原始地址 http://benq.im/2015/05/19/hexomd-07/   文章目录 1. 准备工作 2. 目录语法 ...

  6. Linux tomcat安装详解(未完)

    转: http://blog.csdn.net/lcyaiym/article/details/76696192

  7. unity, 弹出panel一定要放在UI Hierarchy的底端

    如上图,buyPanel放在最底端,为的是它弹出时屏蔽所有其它UI的消息.

  8. GroupCoordinator joingroup源码解析

    转发请注明原创地址 http://www.cnblogs.com/dongxiao-yang/p/7463693.html kafka新版consumer所有的group管理工作在服务端都由Group ...

  9. match函数

    match(s, r [, a]) Return the position in s where the regular expression r occurs, or 0 if r is not p ...

  10. iOS开发UITableViewCell的选中时的颜色设置(转)

    iOS开发UITableViewCell的选中时的颜色设置   1.系统默认的颜色设置 //无色 cell.selectionStyle = UITableViewCellSelectionStyle ...