在ssh中利用Solr服务建立的界面化站内搜索---solr2

     继上次匆匆搭建起结合solr和nutch的所谓站内搜索引擎之后,虽当时心中兴奋不已,可是看了看百度,再只能看看我的控制台的打印出每个索引项的几行文字,哦,好像差距还是有点大……

     简陋的信息显示环境最起码给了我一个信号,这条路没有走错,好吧,让我们来继续探索搜索引擎的奥秘吧。

     上期回顾:上次主要是介绍了solrj,通过solrj的api与solr服务器进行通信,获取服务器上的索引数据以及在编写程序中遇到的一些问题和解决方法。本期主要是建立与solr服务器的通信,提供搜索界面输入关键字或搜索规则,根据关键字或规则到索引数据中寻找匹配项并返回结果到界面上。

    1.本篇的前提是你已经配置好nutch以及solr,并通过网页爬取将索引数据存放到了solr服务器中(solr可以可以部署到tomcat的下也可以不部署,另外我的所有搭建都是在Ubuntu环境下),我配置了中文分词器,以上工作可以在网上搜,资料很多,过程中也有很多错误需要解决,如果有时间我会对这块做个总结,solr服务器的界面如下:

接下来就是要做一个搜索界面,基于是一个纯所搜引擎,所以提供一个招牌、一个输入框以及一个确认按钮即可,关于招牌定什么,问过朋友,有吸引眼球的千度、谷哥哥,一看就是要和度娘们叫板,算了咱不干以卵击石的事,还是有点自知之明的好,最终还是叫“jiesearch”吧——小众,不矫情。这块不涉及什么代码量,所以就多扯了几句,界面如下:

    2.针对上次主题代码进行完善,因为上次返回的是一个SolrDocumentList 对象,不能直接转换为到jsp页面显示的list集合,所以借鉴网上前辈们的指点对代码进行了改写。

 //首先定义HttpSolrServer对象,用于程序连接solr

 1 public class SolrServer {
 2 private static SolrServer solrServer = null;
 3 private static HttpSolrServer server=null;
 4 private static String url="http://solrIP:8080/solr";
 5 
 6 public static synchronized SolrServer getInstance() {
 7      if (solrServer==null){
 8          solrServer=new SolrServer();
 9        }
10         return solrServer;
11 }
12 public static HttpSolrServer getServer(){
13     try {
14         if(server==null){
15             server = new HttpSolrServer(url);
16             server.setSoTimeout(1000); // socket read timeout
17             server.setConnectionTimeout(1000);
18             server.setDefaultMaxConnectionsPerHost(100);
19             server.setMaxTotalConnections(100);
20             server.setFollowRedirects(false); // defaults to false
21             //allowCompression defaults to false.
22             //Server side must support gzip or deflate for this to have any effect.
23             server.setAllowCompression(true);
24             server.setMaxRetries(1); // defaults to 0. > 1 not recommended.
25             }
26       } catch (Exception e) {
27             // TODO Auto-generated catch block
28             e.printStackTrace();
29         }
30     return server;
31     }
32 }

//然后定义一个实体类BlogsDo用于接收和配置索引的各个字段

 1 @Entity
 2 @Table(name="blogs")
 3 public class BlogsDO implements Serializable{
 4     private static final long serialVersionUID = -4721368786493126226L;
 5     @Field("Id")
 6     private String id;
 7     @Field("content")
 8     private String content;
 9     @Field("title")
10     private String title;
11     @Field("url")
12     private String url;
13     @Field("_version_")
14     private String _version_;
15     public String getId() {
16         return id;
17     }
18     public void setId(String id) {
19         this.id = id;
20     }
21     public String getContent() {
22         return content;
23     }
24     public void setContent(String content) {
25         this.content = content;
26      }
27     public String getTitle() {
28         return title;
29     }
30     public void setTitle(String title) {
31         this.title = title;
32     }
33     public String getUrl() {
34         return url;
35     }
36     public void setUrl(String url) {
37         this.url = url;
38     }
39     public String get_version_() {
40         return _version_;
41     }
42     public void set_version_(String version) {
43         _version_ = version;
44     }
45     public static long getSerialversionuid() {
46         return serialVersionUID;
47     }
48 }

备注:这些字段相应的都应该在schema.xml中存在<fields></fields>之间,如下所示,另外个人理解,对于实体类上的注解    @Field("")应该也是一种映射,就是将实体类的字段与配置文件中的选项相对应。

<field name="id" type="string" stored="true" indexed="true"/>
<field name="_version_" type="long" indexed="true" stored="true"/> 
<!-- fields for index-basic plugin -->
<field name="url" type="url" stored="true" indexed="true"required="true"/>
<field name="content" type="text" stored="true" indexed="true"/>
<field name="title" type="text" stored="true" indexed="true"/>

//添加查询规则以及是否高亮的设置以及结果的返回与接收

 1 String searchWord=request.getParameter("searchText");
 2 List<BlogsDO> blogList=new ArrayList<BlogsDO>();
 3 BlogsDO blogsDO=null;
 4 HttpSolrServer solrServer= SolrServer.getInstance().getServer();
 5 SolrQuery sQuery = new SolrQuery();
 6 String para="";
 7 Page page=null;
 8 para="content:"+searchWord+"";
 9 
10 logger.info("para:"+para);
11 sQuery.setQuery(para);
12 sQuery.setStart(0);
13 sQuery.setRows(10);
14 //设置高亮
15 sQuery.setHighlight(true); // 开启高亮组件
16 sQuery.addHighlightField("content");// 高亮字段
17 sQuery.addHighlightField("title");// 高亮字段
18 sQuery.setHighlightSimplePre("<font color='red'>");//标记,高亮关键字前缀
19 sQuery.setHighlightSimplePost("</font>");//后缀
20 sQuery.setHighlightSnippets(2);//结果分片数,默认为1
21 sQuery.setHighlightFragsize(1000);//每个分片的最大长度,默认为100
22 
23 //分片信息
24 sQuery.setFacet(true)
25 .setFacetMinCount(1)
26 .setFacetLimit(5)//段
27 .addFacetField("content");//分片字段
28 
29 long startSearch=System.currentTimeMillis();
30 Integer counts=0;
31 try {
32     QueryResponse response = solrServer.query(sQuery);
33     SolrDocumentList list = response.getResults();
34     counts=(int) list.getNumFound();//搜索数量
35     logger.info("counts:"+counts);
36     //获取所有高亮的字段
37     Map<String,Map<String,List<String>>> highlightMap=response.getHighlighting();
38     String blogId="";
39     for (SolrDocument solrDocument : list) {
40     blogsDO=new BlogsDO();
41     blogId=(String) solrDocument.getFieldValue("id").toString();
42     blogsDO.setId(blogId);
43     blogsDO.set_version_(solrDocument.getFieldValue("_version_").toString());
44     blogsDO.setUrl(solrDocument.getFieldValue("url").toString());
45 
46     List<String> titleList=highlightMap.get(blogId).get("title");
47     List<String> contentList=highlightMap.get(blogId).get("content");
48     if(titleList!=null && titleList.size()>0){
49         blogsDO.setTitle(titleList.get(0));
50     }else{
51     //获取并设置高亮的字段title
52     blogsDO.setTitle(solrDocument.getFieldValue("title").toString());
53     }
54     if(contentList!=null && contentList.size()>0){
55         blogsDO.setContent(contentList.get(0));
56      }else{
57     //获取并设置高亮的字段content
58         blogsDO.setContent(solrDocument.getFieldValue("content").toString());
59     }
60     blogList.add(blogsDO);
61     }
62 } catch (SolrServerException e) {
63     e.printStackTrace();
64 }
65 long endSearch=System.currentTimeMillis();
66 model.addObject("time", (double)(endSearch-startSearch)/1000);
67 model.addObject("counts", counts);
68 model.addObject("blogList", blogList);

3.下面要做的就是在前台jsp页面中接收list集合和传过去的counts(搜索结果个数),time(搜索耗时)并相应的调整界面布局即可,效果如下:

     至此一个搜索引擎做的算是有点模样了,下一步如果还有时间可以对本地文档图片等建立索引并实现搜索功能。

    另外最近我在看大数据可视化方面的东西,如果有兴趣有见解的可以交流下

邮箱:zjhxp_1990@163.com

文中如有不足和错误还请指正!

    参考博文:http://blog.csdn.net/chunming8302/article/details/7321501

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏恰童鞋骚年

.NET单元测试的艺术-2.核心技术

开篇:上一篇我们学习基本的单元测试基础知识和入门实例。但是,如果我们要测试的方法依赖于一个外部资源,如文件系统、数据库、Web服务或者其他难以控制的东西,那又该...

12420
来自专栏AI星球

Eclipse中使用JUnit4进行单元测试(整合篇)

我们在编写大型程序的时候,需要写成千上万个方法或函数,这些函数的功能可能很强大,但我们在程序中只用到该函数的一小部分功能,并且经过调试可以确定,这一小部分功能是...

22520
来自专栏walterlv - 吕毅的博客

利用 ReSharper 自定义代码中的错误模式,在代码审查之前就发现并修改错误

发布于 2018-03-20 11:54 更新于 2018-03...

9400
来自专栏老马寒门IT

Node入门教程(13)第十一章:mocha单元测试+should断言库+istanbul覆盖率测试+art-template

声明: 以下为老马的全栈视频教程的笔记,如果需要了解详情,请直接配合视频学习。视频全部免费,视频地址:https://ke.qq.com/course/2945...

16200
来自专栏奔跑的蛙牛技术博客

分布式对象之客户\服务器角色以及RMI初探

程序员希望通过无所不在的java对象来作为所有问题的解决之道,思想就是通过网络请求相互协作。我可以调用一个远程对象帮我得到我所要的信息,并作为响应的一部分返回

19610
来自专栏冰霜之地

如何设计并实现一个线程安全的 Map ?(下篇)

在上篇中,我们已经讨论过如何去实现一个 Map 了,并且也讨论了诸多优化点。在下篇中,我们将继续讨论如何实现一个线程安全的 Map。说到线程安全,需要从概念开始...

61970
来自专栏梧雨北辰的开发录

iOS面试知识总结之基本概念总结

凡经历过iOS面试的我们总会发觉,即使实际开发中做过许多项目,也难免为一个普通的面试题受挫。这也许不是因为我们技术不过关,而是因为在平时我们忽略了怎样将用到的知...

42470
来自专栏Java架构

阿里、华为、腾讯、京东、百度Java技术面试题精选

37460
来自专栏前端达人

JavaScript基础——回调(callback)是什么

上篇文章《JavaScript基础——你真的了解JavaScript吗?》,我们明白了JavaScript是一个单线程、非阻塞、异步、解释性语言,清楚了什么是单...

26670
来自专栏华章科技

干货:手把手教你用Python读写CSV、JSON、Excel及解析HTML

导读:本文要介绍的这些技法,会用Python读入各种格式的数据,并存入关系数据库或NoSQL数据库。

28720

扫码关注云+社区

领取腾讯云代金券