- 浏览: 47260 次
- 性别:
- 来自: 成都
最新评论
[size=medium]最近刚忙完一个电影网站,其中的全文搜索的功能我就是用Solr完成的,在此将我在开发中遇到的问题以及怎样解决问题的经验拿出来与大家分享。
我们这个网站有一个站内搜索的功能,例如站内新闻,输入关键字去搜索。数据库里有上万条数据,如果去挨个like,效率会很低,经领导指点,说可以试一试HibernateSearch和Apache solr结合mmseg4j分词进行全文检索,于是我就开始我的Solr之旅。
一开始在网上搜了很多例子拿来入门,首先是分词,mmseg4j是用来分词的,常用的分词分析器有三种:MaxWordAnalyzer(最大分词),SimpleAnalyzer(简单的),ComplexAnalyzer(复杂的),最开始我用的是ComplexAnalyzer,看上去很不错,后来遇到了个小问题,例如“吴宇森吃羊肉串”,经过ComplexAnalyzer分分词后,用Solr去搜“吴宇森”会返回想要的结果,但是“吴宇”去搜什么也没返回。这是一个让人很头疼的问题,于是我试验了MaxWordAnalyzer,发现“吴宇”,“吴宇森”都能返回正确的结果,这才是我们想要的。
一段测试例子,大家可以拿去试一下MaxWordAnalyzer,SimpleAnalyzer,ComplexAnalyzer之间的区别。
Java代码
可见mmseg4j是以非常灵活的分词工具而且分词速度也很快,2.5M的长篇小说用Complex模式是5.3秒左右,用Simple模式是2.9秒左右,好的,分词搞定了。再提一点,如何将mmseg4j应用到我们的Entity上的,我用的是元数据声明的方式:
Java代码
这里面的name = "newTitle",name = "newsSummry",是生成索引的名称,同时还要在Solr的schema.xml里定义与之相对应的field:
Xml代码
说到这,再提一下如何将集合建立索引以及配置,例如OneToMany,首先在一的一端进行声明:
Java代码
然后在多的一端指定到底是哪一个字段建立索引:
Java代码
在这里你可以不给你的索引字段加name,默认会在索引库里有name="plotKeywords.summary"这样一个索引名称,同时也不要忘记在Solr的schema.xml里定义与之相对应的field:
Xml代码
type="textMax" ,对应schema.xml里的:
Xml代码
dicPath="D:/data/dict"是词库的路径,如果我们用的是MaxWordAnalyzer进行的分词,那么为了保证Solr能搜到我们想要的结果,必须在schema.xml里配置上面一段fieldType,指定mode="max-word",这样Solr就会按照最大分词去给我们返回与之相对应的结果,“吴宇”,“吴宇森”,都会返回结果。
如何将Solr集成到我们的项目中呢?很简单,就拿Tomcat举例,解压Solr,将..\apache-solr-1.3.0\example\solr 文件夹拷贝到Tmocat的bin文件夹下,配置schema.xml上面提到了,还有索引库路径,在solrconfig.xml里配置:
Xml代码
然后在web.xml里面配置Solr的SolrDispatchFilter:
Xml代码
在这里就不提引入的第三方jar文件,可以参考Solr文档。要注意的是HibernateSearch结合mmseg4j分词时候,我们用到了自己的词库,需要指定一个虚拟机参数:-Dmmseg.dic.path=d:/data/dict,在这里我们将分词用到的词库放到了d:/data/dict,有可能词库过大造成虚拟机内存溢出,还要加参数: -Xmx256m -Xmx512m。就这样Solr就集成到我们的项目中了,而且HibernateSearch帮我们管理了索引库,增加,删除,还有修改没有个被索引的字段,HibernateSearch都会帮我们同步索引库。
Solr的查询语法很灵活,大家可以参考官方文档,在这里我要提一下查询or和and,Solr默认的配置是or,在schema.xml里:
Xml代码
如果想用到and,还有一种方式在Url里指定参数fq,过滤条件,例如:q=kaka&fq=age:[15 to 20],搜索条件是kaka,并且age是15到20岁之间。
Solr支持很多种查询输出格式,用参数wt指定,有xml, json, php, phps,我这里用到了json。一段JavaScript供大家参考:
Js代码
一切都顺利进行,但是马上就遇到了一个新问题,重建索引后Solr也必须重新拿启动,要么Solr不会用最新的索引库,Solr有自己的缓存,这个很让让人头疼,如果删除一条数据,HibernateSearch会帮我们同步索引库,但是Solr的缓存还是缓存之前没有删除的数据。我试图通过配置文件不用Solr的缓存,但是没有效果,根据官方文档上说的意思是:Solr的缓存是干不掉的。这绝对不是我们想要的结果,但是最后还是解决了,在sorlconfig.xml里配置:
Xml代码
然后访问/update?commit=true,Solr就会放弃之前的缓存,去重新检索我们的索引库建立新的缓存,这正是我们想要的结果。[/size]
我们这个网站有一个站内搜索的功能,例如站内新闻,输入关键字去搜索。数据库里有上万条数据,如果去挨个like,效率会很低,经领导指点,说可以试一试HibernateSearch和Apache solr结合mmseg4j分词进行全文检索,于是我就开始我的Solr之旅。
一开始在网上搜了很多例子拿来入门,首先是分词,mmseg4j是用来分词的,常用的分词分析器有三种:MaxWordAnalyzer(最大分词),SimpleAnalyzer(简单的),ComplexAnalyzer(复杂的),最开始我用的是ComplexAnalyzer,看上去很不错,后来遇到了个小问题,例如“吴宇森吃羊肉串”,经过ComplexAnalyzer分分词后,用Solr去搜“吴宇森”会返回想要的结果,但是“吴宇”去搜什么也没返回。这是一个让人很头疼的问题,于是我试验了MaxWordAnalyzer,发现“吴宇”,“吴宇森”都能返回正确的结果,这才是我们想要的。
一段测试例子,大家可以拿去试一下MaxWordAnalyzer,SimpleAnalyzer,ComplexAnalyzer之间的区别。
Java代码
import java.io.IOException; import junit.framework.TestCase; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.queryParser.ParseException; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; import com.chenlb.mmseg4j.analysis.MaxWordAnalyzer; public class LuceneUseSimpleAnalyzerTest extends TestCase { Directory dir; Analyzer analyzer; @Override protected void setUp() throws Exception { String txt = "吴宇森吃羊肉串"; //analyzer = new SimpleAnalyzer(); //analyzer = new ComplexAnalyzer(); //分词分析器 analyzer = new MaxWordAnalyzer(); //内存索引对象 dir = new RAMDirectory(); IndexWriter iw = new IndexWriter(dir, analyzer); Document doc = new Document(); //Field.Store.YES表示在索引里将整条数据存储 doc.add(new Field("txt", txt, Field.Store.YES, Field.Index.ANALYZED)); iw.addDocument(doc); iw.commit(); iw.optimize(); iw.close(); } public void testSearch() { try { //实例化搜索器 IndexSearcher searcher = new IndexSearcher(dir); //构造Query对象 QueryParser qp = new QueryParser("txt", analyzer); Query q = qp.parse("吴宇森"); System.out.println(q); //搜索相似度最高的10条 TopDocs tds = searcher.search(q, 10); //命中的个数 System.out.println("======size:" + tds.totalHits + "========"); //输出返回结果 for (ScoreDoc sd : tds.scoreDocs) { System.out.println(sd.score); System.out.println(searcher.doc(sd.doc).get("txt")); } } catch (CorruptIndexException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } } }
可见mmseg4j是以非常灵活的分词工具而且分词速度也很快,2.5M的长篇小说用Complex模式是5.3秒左右,用Simple模式是2.9秒左右,好的,分词搞定了。再提一点,如何将mmseg4j应用到我们的Entity上的,我用的是元数据声明的方式:
Java代码
@Field(name = "newsTitle", store = Store.YES, index = Index.TOKENIZED, analyzer = @Analyzer(impl = MaxWordAnalyzer.class)) private String title; @Field(name = "newsSummary", store = Store.YES, index = Index.TOKENIZED, analyzer = @Analyzer(impl = MaxWordAnalyzer.class)) private String summary; @Field(name = "newsPublishedTime", store = Store.YES, index = Index.TOKENIZED, analyzer = @Analyzer(impl = MaxWordAnalyzer.class)) private Date publishedTime;
这里面的name = "newTitle",name = "newsSummry",是生成索引的名称,同时还要在Solr的schema.xml里定义与之相对应的field:
Xml代码
<field name="newsTitle" type="textMax" indexed="true" stored="true"/> <field name="newsSummary" type="textMax" indexed="true" stored="true"/> <field name="newsPublishedTime" type="date" indexed="true" stored="true" default="NOW" multiValued="false"/>
说到这,再提一下如何将集合建立索引以及配置,例如OneToMany,首先在一的一端进行声明:
Java代码
@IndexedEmbedded private Set<PlotKeyword> plotKeywords = new HashSet<PlotKeyword>(); //关键词联想
然后在多的一端指定到底是哪一个字段建立索引:
Java代码
@Field(store = Store.YES, index = Index.TOKENIZED, analyzer = @Analyzer(impl = MaxWordAnalyzer.class)) private String summary;
在这里你可以不给你的索引字段加name,默认会在索引库里有name="plotKeywords.summary"这样一个索引名称,同时也不要忘记在Solr的schema.xml里定义与之相对应的field:
Xml代码
<field name="plotKeywords.summary" type="textMax" indexed="true" stored="true"/>
type="textMax" ,对应schema.xml里的:
Xml代码
<fieldType name="textMax" class="solr.TextField" positionIncrementGap="100" > <analyzer> <tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="D:/data/dict"/> <filter class="solr.LowerCaseFilterFactory"/> </analyzer> </fieldType>
dicPath="D:/data/dict"是词库的路径,如果我们用的是MaxWordAnalyzer进行的分词,那么为了保证Solr能搜到我们想要的结果,必须在schema.xml里配置上面一段fieldType,指定mode="max-word",这样Solr就会按照最大分词去给我们返回与之相对应的结果,“吴宇”,“吴宇森”,都会返回结果。
如何将Solr集成到我们的项目中呢?很简单,就拿Tomcat举例,解压Solr,将..\apache-solr-1.3.0\example\solr 文件夹拷贝到Tmocat的bin文件夹下,配置schema.xml上面提到了,还有索引库路径,在solrconfig.xml里配置:
Xml代码
<dataDir>${solr.data.dir:D:/data/index}</dataDir>
然后在web.xml里面配置Solr的SolrDispatchFilter:
Xml代码
<filter> <filter-name>SolrRequestFilter</filter-name> <filter-class>org.apache.solr.servlet.SolrDispatchFilter</filter-class> </filter> <filter-mapping> <filter-name>SolrRequestFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
在这里就不提引入的第三方jar文件,可以参考Solr文档。要注意的是HibernateSearch结合mmseg4j分词时候,我们用到了自己的词库,需要指定一个虚拟机参数:-Dmmseg.dic.path=d:/data/dict,在这里我们将分词用到的词库放到了d:/data/dict,有可能词库过大造成虚拟机内存溢出,还要加参数: -Xmx256m -Xmx512m。就这样Solr就集成到我们的项目中了,而且HibernateSearch帮我们管理了索引库,增加,删除,还有修改没有个被索引的字段,HibernateSearch都会帮我们同步索引库。
Solr的查询语法很灵活,大家可以参考官方文档,在这里我要提一下查询or和and,Solr默认的配置是or,在schema.xml里:
Xml代码
<!-- SolrQueryParser configuration: defaultOperator="AND|OR" --> <solrQueryParser defaultOperator="OR"/>
如果想用到and,还有一种方式在Url里指定参数fq,过滤条件,例如:q=kaka&fq=age:[15 to 20],搜索条件是kaka,并且age是15到20岁之间。
Solr支持很多种查询输出格式,用参数wt指定,有xml, json, php, phps,我这里用到了json。一段JavaScript供大家参考:
Js代码
$.ajax({ type: "post",//使用post方法访问后台 dataType: "json",//返回json格式的数据 url: "/select/",//要访问的后台地址 data: "q=" + keywords + "&start=" + 0 + "&rows=" + 5 + "&indent=" + "on" + "&wt=" + "json" + "&sort=" + "newsPublishedTime asc",//要发送的数据 success: function(j) {//msg为返回的数据,在这里做数据绑定 var docs = j.response.docs; for (var i=0; i<docs.length; i++) { var date = docs[i].newsPublishedTime; var title = docs[i].newsTitle; var summary = docs[i].newsSummary; } } });
一切都顺利进行,但是马上就遇到了一个新问题,重建索引后Solr也必须重新拿启动,要么Solr不会用最新的索引库,Solr有自己的缓存,这个很让让人头疼,如果删除一条数据,HibernateSearch会帮我们同步索引库,但是Solr的缓存还是缓存之前没有删除的数据。我试图通过配置文件不用Solr的缓存,但是没有效果,根据官方文档上说的意思是:Solr的缓存是干不掉的。这绝对不是我们想要的结果,但是最后还是解决了,在sorlconfig.xml里配置:
Xml代码
<requestHandler name="/update" class="solr.XmlUpdateRequestHandler" />
然后访问/update?commit=true,Solr就会放弃之前的缓存,去重新检索我们的索引库建立新的缓存,这正是我们想要的结果。[/size]
发表评论
-
nutch-乱码解决(转)
2011-06-02 00:45 3425ubuntu下nutch-1.0的安装和配置错误排除(原创 ... -
nutch 抓取动态网页(转)
2011-06-02 00:38 1314解决搜索动态内容的问题: 需要注意在conf下面的2个文件:r ... -
Solr在TomCat下的使用 和 运行多个Solr (转)
2010-11-08 15:55 1328一、在Tomcat中安装运行Solr 下载Solr包,找到d ... -
(转)Solr笔记 Schema.xml和solrconfig.xml分析
2010-11-08 15:39 1546现在我们开始研究载入的数据部分(importing data) ... -
solr的分布式部署
2010-11-03 20:30 2106需求: 实现SOLR主,辅服务器更新同步,每次客户端COMM ... -
在Tomcat中使用solr
2010-11-03 19:32 1189====== ====== ==== 单个 Solr ... -
solr技术文档
2010-11-03 19:25 1534pan_java 写道SOLR技术文档 1. 了解lucene ... -
solr二次开发之solrj(转载)
2010-11-02 20:59 7585Solrj已经是很强大的solr客户端了。它本身就包装了htt ... -
Solr学习笔记
2010-10-30 16:13 1031准备: Tomcat版本:apache-tomcat-7.0. ...
相关推荐
《Hibernate Search in Action》是一本深入探讨Hibernate Search技术的专业书籍,配合源代码一同学习,能够帮助读者更好地理解和应用这项强大的全文检索和分析框架。Hibernate Search是Hibernate ORM的一个扩展,它...
1. **Spring框架**:Spring是一个开源的Java企业级应用框架,提供依赖注入、AOP(面向切面编程)、MVC(模型-视图-控制器)等核心特性,极大地简化了Java应用的开发过程。 2. **Hibernate ORM**:Hibernate是一个...
这个压缩包"hibernate-search-4.5.2.Final-dist.tar.gz"包含了Hibernate Search 4.5.2.Final版本的所有组件和资源,是开发人员进行企业级搜索解决方案构建的重要工具。 一、Hibernate Search概述 Hibernate Search...
- **Apache Solr** 另一个基于Lucene的搜索平台,专注于企业级搜索。它提供了更丰富的管理和配置选项,适合大型项目。 - **XML/JSON接口**:Solr使用XML或JSON进行通信,允许通过HTTP请求发送查询和管理索引。 6....
Struts2+Spring3+Hibernate3是Java开发中常见的企业级应用框架组合,被称为SSH框架。这个商城系统利用这三个框架的协同工作,构建了一个高效、稳定且功能丰富的平台。接下来,我们将深入探讨这些关键技术及其在商城...
SSH2框架是企业级Java开发的常用选择,它由Struts2、Spring和Hibernate三个组件构成,分别负责MVC模式、依赖注入和持久化层。将Lucene与SSH2结合,可以在Web应用程序中实现强大的搜索功能。 集成Lucene到SSH2框架中...
Lucene常与其他框架结合使用,如Spring Data Solr、Hibernate Search等,实现企业级搜索解决方案。同时,它也被用于搜索引擎开发、日志分析、推荐系统等领域。 综上所述,Lucene作为一款强大的全文搜索引擎库,其...
Solr是另一个强大的搜索引擎,适合大型企业级应用。这两者都支持复杂的查询语法和丰富的数据分析功能。 结合以上技术,我们可以创建一个完整的系统,如:Java网络爬虫负责定期抓取网站数据,然后将数据存储到数据库...
Lucene可以与Spring、Hibernate等框架集成,方便在企业级应用中使用。例如,Solr和Elasticsearch都是基于Lucene的搜索引擎服务,提供了更高级的管理和部署选项。 总之,Lucene作为Java的全文检索库,为开发者提供...
第一个项目是淘嘟嘟网上商城,他参与了需求分析和项目构建,负责商品管理、广告管理和搜索展示。项目采用了SpringMVC、MyBatis、jQuery、FastDFS、Redis、Solr、Maven等技术。他利用Maven提高了开发效率,使用Solr...
**Lucene.jar 架包详解** ...无论是在小型项目还是大型企业级应用中,Lucene 都是一个不可或缺的工具。通过熟练掌握 Lucene,开发者可以有效地提升应用的搜索体验,满足用户对信息获取的快速和精确需求。
SSH框架是指Spring、Struts和Hibernate三个开源框架的组合,它们在Java领域中被广泛用于构建企业级应用。 Spring框架是核心,它提供了一个全面的编程和配置模型,旨在简化企业级应用的开发。Spring提供了依赖注入...
此外,为了提高系统的性能和用户体验,可能还会涉及到缓存技术(如Spring Cache)、搜索引擎集成(如Solr或Elasticsearch)以优化菜品搜索,以及安全框架(如Spring Security)来保障用户的账户安全。而测试方面,...
9. **应用场景**:Lucene广泛应用于企业级的搜索应用,如内容管理系统、电子商务平台、知识库系统等。 10. **与其他工具结合**:在实际开发中,Lucene常常与Spring Data、Hibernate Search等框架集成,以简化应用...
企业门户新闻网系统是一种基于Java技术开发的企业级应用,旨在整合企业内部信息资源,提供统一的访问入口,提高信息共享和工作效率。在Java平台下构建这样的系统,开发者通常会利用Spring框架来实现业务逻辑,...
SSH框架,全称为Spring、Struts和Hibernate,是Java领域广泛应用的企业级开发框架组合,具有良好的模块化和可扩展性,使得开发复杂的Web应用程序变得更为简便。 1. **Spring框架**:Spring作为核心容器,负责管理...
9. **搜索引擎集成**:为了方便用户搜索,可能集成了Solr或Elasticsearch等全文搜索引擎,提供高效的全文检索功能。 10. **容器化部署**:Docker容器化技术可能用于部署,通过Dockerfile定义运行环境,确保应用在...
7. **扩展与优化**:这个电商平台可能还涉及到了缓存策略(如使用Spring Cache)、搜索引擎集成(如Solr或Elasticsearch)、性能监控(如使用Spring Boot Actuator)等高级特性。开发者可以基于此源码进行功能扩展和...