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. C#秘密武器之LINQ to SQL

    LINQ to SQL语句(1)之Where 适用场景:实现过滤,查询等功能. 说明:与SQL命令中的Where作用相似,都是起到范围限定也就是过滤作用的,而判断条件就是它后面所接的子句.Where操 ...

  2. 基于.NET的轻量级微信SDK

    一.前言 特别不喜欢麻烦的一个人,最近碰到了微信开发.下载下来了一些其他人写的微信开发“框架”,但是被恶心到了,实现的太臃肿啦. 最不喜欢的就是把微信返回的xml消息在组装成实体类,所以会比较臃肿,现 ...

  3. Selenium webdriver Java 高级应用

    对于这一段还蛮有感慨的,只想说,代码还是需要自己去敲的. 1. 改变用户代理 import org.junit.AfterClass; import org.junit.BeforeClass; im ...

  4. grid 布局 属性示例

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  5. js 值和类型

    js中变量是没有类型的,只有值才有类型. 变量随时可以持有任何类型的值. <!DOCTYPE html> <html lang="zh"> <head ...

  6. 神秘值分解(Singular Value Decomposition)

    - 线性变化的几何表现 首先看下简单的矩阵,这是一个对角矩阵 M=(3001) 我们先用这个对角矩阵乘以一个点来看看它的几何变化. (3001)∗(xy)=(3xy) 在几何上就相当于把原来的向量x轴 ...

  7. 百度MUX:APP动效之美需内外兼修

    移动互联网时代已经到来.APP已如天空的繁星.数也数不清.随着手机硬件的不断升级,实现炫酷且流畅的动效不再是遥远的梦想.假设你是APP达人,喜欢试用各种APP,你肯定会发现越来越多的APP開始动效化. ...

  8. hdu1236 排名(结构体排序)

    排名 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submiss ...

  9. 【Python3 爬虫】10_Beautiful Soup库的使用

    之前学习了正则表达式,但是发现如果用正则表达式写网络爬虫,那是相当的复杂啊!于是就有了Beautiful Soup 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓 ...

  10. 基于React实现的【绿色版电子书阅读器】,支持离线下载

    代码地址如下:http://www.demodashi.com/demo/12052.html MyReader 绿色版电子书阅读器 在线地址:http://myreader.linxins.com ...