`
winnerlxh
  • 浏览: 92209 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

hibernate的全文搜索(Lucene)

阅读更多
1)文件全文搜索
首先导入三个核心包(hibernate-search.jar、hibernate-commons-annotations.jar和lucene-core.jar)和一个高亮的包(lucene-highlighter-2.0.0.jar)到web app里面;
创建索引数据库类:
package com.golden.info.test;
import java.io.File;
import net.paoding.analysis.analyzer.PaodingAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexWriter;
/**
* @author liuxh
*初始化检索库
*/
public class CreateDataBase{
    public CreateDataBase(){ 
    }
    public int createDataBase(File file){
       int returnValue=0;
       if(!file.isDirectory()){
           file.mkdirs();
       }
       try{
           IndexWriter indexWriter= new IndexWriter(file,new StandardAnalyzer(),true);
           indexWriter.close();
           returnValue=1;
       }catch(Exception ex){
           ex.printStackTrace();
       }
       return returnValue;
    }
    /**
     *传入检索库路径,初始化库
     * @paramfile
     * @return
     */
    public int createDataBase(String file){
       return this.createDataBase(new File(file)); 
    }
    public static void main(String[]args){
       CreateDataBase temp= new CreateDataBase();
       if(temp.createDataBase("e:\\lucene\\holendb")==1){ //创建数据库存放的路径
           System.out.println("数据库初始化成功");
       }
    }
}
然后添加记录:
package com.golden.info.test;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
/**
* @author liuxh
*记录加载
*/
public class InsertRecords{
    public InsertRecords(){
    }
    public int insertRecords(String dbpath,File file){
       int returnValue=0;
       try{
           IndexWriter indexWriter = new IndexWriter(dbpath,new StandardAnalyzer(),false);
           this.addFiles(indexWriter,file);
           returnValue=1;
       }catch(Exception ex){
           ex.printStackTrace();
       }
       return returnValue;
    }
    /**
     *传入需加载的文件名
     * @paramfile
     * @return
     */
    public int insertRecords(String dbpath,String file){
       return this.insertRecords(dbpath,new File(file));
    }
    public void addFiles(IndexWriter indexWriter,File file){
       Document doc= new Document();
       try{
           doc.add(new Field("filename",file.getCanonicalPath(),Field.Store.YES,Field.Index.UN_TOKENIZED)); //注
           doc.add(new Field("content",this.chgFileToString(file),Field.Store.YES,Field.Index.TOKENIZED));//注
           indexWriter.addDocument(doc);
           indexWriter.close();
       }catch(Exception ex){
           ex.printStackTrace();
       }
    }
    /**
     *从文本文件中读取内容
     * @paramfile
     * @return
     */
    public String chgFileToString(File file){
       String returnValue= null;
       StringBuffer sb= new StringBuffer();
       char[]c= new char[4096];
       try{
       //读取的文件必须是UTF-8格式的,不然读出来的中文为乱码
           Reader reader= new FileReader(file);
           int n=0;
           while(true){           
              n=reader.read(c);
              if(n>0){
                  sb.append(c,0,n);
              }else{
                  break;
              }
           }
           reader.close();
       }catch(Exception ex){
           ex.printStackTrace();
       }
       returnValue=sb.toString();
       return returnValue;
    }
    public static void main(String[] args){
       InsertRecords temp= new InsertRecords();
       String dbpath="e:\\lucene\\holendb";
       //holen1.txt中包含关键字"holen"和"java"
       if(temp.insertRecords(dbpath,"e:\\lucene\\holen1.txt")==1){
           System.out.println("添加文件成功");
       }
       //holen2.txt中包含关键字"holen"和"chen"
       if(temp.insertRecords(dbpath,"e:\\lucene\\holen2.txt")==1){
           System.out.println("添加文件成功");
       } 
    }
}
注:lucene 2.0中去掉了Field.Text和Field.KeyWord,不过网上的sample code还在用,所以会造成许多刚接触lucene的人遇到问题,我就是其中一个。
新的写法需要直接new一个Field对象:
Reader txtReader = new FileReader(f);
doc.add(new Field(”path”,f.getCanonicalPath(),Field.Store.YES,Field.Index.UN_TOKENIZED));
doc.add(new Field(”contents”,txtReader));
不过Field.Index.UN_TOKENIZED也即将在lucene3中消失了,到时候又要改了。
查询方法并高亮关键字:
package com.golden.info.test;
import java.io.StringReader;
import java.util.ArrayList;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
/**
* @author liuxh
*检索查询
*/
public class QueryRecords{
    public QueryRecords(){
    }
    /**
     *检索查询,将结果集返回
     * @param searchkey
     * @param dbpath
     * @param searchfield
     * @return
     */
    public ArrayList queryRecords(String searchkey,String dbpath,String searchfield){
       ArrayList list= null;
       try{
           Searcher searcher= new IndexSearcher(dbpath);
//           对于单个字段进行查询
//           QueryParser parse=new QueryParser(searchfield,new StandardAnalyzer());
//           Query query =parse.parse(searchkey);
// 对多个字段进行查询
           String[] productFields = {"filename", "content"};
           QueryParser parse = new MultiFieldQueryParser(productFields, new StandardAnalyzer()); 
           parse.setAllowLeadingWildcard(true);
           Query query=parse.parse(searchkey);
           Hits hits=searcher.search(query);
           if(hits!= null){
              list= new ArrayList();
              int temp_hitslength=hits.length();
              Document doc= null;
              Analyzer analyzer = new StandardAnalyzer();
            //高亮显示设置
              Highlighter highlighter = null;
              SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<read>","</read>");  
              highlighter = new Highlighter(simpleHTMLFormatter,new QueryScorer(query));     
              highlighter.setTextFragmenter(new SimpleFragmenter(100));//这个100是指定关键字字符串的context的长度,你可以自己设定,因为不可能返回整篇正文内容
              for(int i=0;i<temp_hitslength;i++){
              doc=hits.doc(i);
              TokenStream tokenStream2 =analyzer.tokenStream("filename", new StringReader(doc.get("filename")));
                  list.add(highlighter.getBestFragment(tokenStream2,doc.get("filename")));
                  TokenStream tokenStream =analyzer.tokenStream("content", new StringReader(doc.get("content")));
                  list.add(highlighter.getBestFragment(tokenStream,doc.get("content")));
              }
           }
       }catch(Exception ex){
           ex.printStackTrace();
       }
       return list;
    }
    public static void main(String[]args){
       QueryRecords temp= new QueryRecords();     
       ArrayList list= null;
       //搜索在那个字段中的内容,其中第一个参数为查询关键字,第二个参数为库文件的路劲,第三个参数为字段名字
       list=temp.queryRecords("holen 我游 lucene","e:\\lucene\\holendb","content");
       for(int i=0;i<list.size();i++){
           System.out.println((String)list.get(i));
       }     
    }
}
2)数据库全文搜索
首先,我们需要将相关配置添加到persistence.xml中,如下:
<!-- use a file system based index -->
<property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider" />
<!-- directory where the indexes will be stored -->
<property name="hibernate.search.default.indexBase" value="[/path/to/your/location/directory]" />
<property name="hibernate.ejb.event.post-insert" value="org.hibernate.search.event.FullTextIndexEventListener" />
<property name="hibernate.ejb.event.post-update" value="org.hibernate.search.event.FullTextIndexEventListener" />
<property name="hibernate.ejb.event.post-delete" value="org.hibernate.search.event.FullTextIndexEventListener" /> 

这样我们就设置好了类路径、索引路径、索引操作监听器路径。下面,我们需要添加hibernate-search.jar、hibernate-commons-annotations.jar和lucene-core.jar到你的ear里面。
好了,现在,我们需要告诉Hibernate Search哪个对象被索引,并且我们会对哪些属性感兴趣。
@Entity
@Name("product")
@Indexed
public class Product implements Serializable {
    static final long serialVersionUID = 1l;
   @Id @GeneratedValue @DocumentId 
    private Long id; 
     @NotNull 
    @Field(index = Index.TOKENIZED) 
    private String name;   
    @NotNull 
    @Field(index = Index.TOKENIZED) 
private String description; 
    // getters and setters 

@Indexed注解用来告诉Hibernate Search该持久类是拥有索引的。@DocumentId注解用来标明这个属性是这个对象的ID,并且未被编入索引。此外,我们还有两个属性,分别是 name和description。这两个属性都用@Field标注,这样Hibernate Search就被允许分析处理这两个属性。其他可选的属性有Index.NO(不要被分析)、Index.UN_TOKENIZED(不要被分析器预先处理)、Index.NO_NORM(不需要存储的普通属性)。
现在,我们已经拥有了Lucene的所有索引,我们还需要一个搜索的方法。所以我们需要建立一个SearchManager类。
@Name("SearchManager") 
public class SearchManager {
@In
private FullTextEntityManager entityManager; 
private String searchPattern; 
// getters and setters for searchPattern 
public List getResults() { 
Map boostFields = new HashMap(2); 
// increase the importance of the name field  
// over the other product fields 
boostFields.put("name", 4f);  
String[] productFields = {"name", "description"}; 
QueryParser parser = new MultiFieldQueryParser(productFields, new StandardAnalyzer(), boostFields);  parser.setAllowLeadingWildcard(true);
Query luceneQuery; 
try { 
luceneQuery = parser.parse(searchPattern); 
} catch (ParseException pe) { 
log.error("found a problem in search", pe); 
return null; 

// extract the products     
List products =entityManager.createFullTextQuery(luceneQuery, Product.class). 
setMaxResults(20).getResultList(); 
return products; 


好了,现在我们可以创建search.xhtml文件,用来显示搜索结果了。下面是该文件的一个片段。
<rich:dataGrid value="#{SearchManager.results}" var="garage">
    [ loop over the values ]
</rich:dataGrid>
然后,在pages.xml中添加一个到search.xhtml的入口。
<page view-id="/search.xhtml">
    <param name="searchPattern" value="#{SearchManager.searchPattern}"/>
</page>
还剩下一个步骤。我们需要添加一个搜索框到菜单里面。如果你使用了Seam的默认布局,你就会看见/view/layout文件夹下面有一个menu.xhtml文件。如果没有找到,只需要将下面这一段添加到你需要的地方:
<h:form id="search_form">
    <h:inputText id="searchPattern" required="true" value="#{SearchManager.searchPattern}" />
    <h:commandButton action="/search.xhtml" value="search"></h:commandButton>
</h:form>
现在,你可以开始搜索你想要的对象了。是不是非常简单?但是,如果对象的一个属性是用来表示这个对象是否能显示在页面上,那应该怎么办?好的,在这种情况下,你需要添加一个过滤器。过滤器都继承自org.apache.lucene.search.Filter类。
想象一下,我们在产品类上有一个属性是用来标明产品的状态的,这个属性有三种值"L"表示有效的产品,"D"表示被删除的产品,"P"表示待发布的产品。显然,在用户搜索的时候,我们只想显示出可见的产品。所以我们需要添加一个过滤器:
1. public class LiveProductFilter extends Filter { 
2.     private static final long serialVersionUID = 1l; 
3.     public BitSet bits(IndexReader reader) throws IOException { 
4.         BitSet bitSet = new BitSet( reader.maxDoc() ); 
5.         TermDocs termDocs = reader.termDocs( new Term("status", "L") ); 
6.         while ( termDocs.next() ) { 
7.             bitSet.set( termDocs.doc() ); 
8.         } 
9.          return bitSet; 
10.         } 
11. } 
为了让Hibernate Search能够找到我们在产品类上添加的过滤器,我们需要添加下面这个注解:
@FullTextFilterDefs ( { @FullTextFilterDef(name="liveProduct", impl = LiveProductFilter.class, cache=false) })好了,就写到这里。
参考文件:http://huxiuliang.iteye.com/blog/583136
注:数据库全文搜索暂时没有配置成功,加载监听器的时候报找不到类文件
分享到:
评论

相关推荐

    Hibernate 与 Lucene 的整合框架详解

    Hibernate 和 Lucene 分别作为对象关系映射(ORM)工具和全文搜索引擎,在各自领域内都有广泛的应用。将两者进行整合,可以实现对数据库中数据的有效索引和快速搜索,极大地提高应用程序的性能。 #### 二、整合框架...

    Lucene Hibernate

    标题“Lucene Hibernate”揭示了我们讨论的核心主题:如何将Apache Lucene这个强大的全文搜索引擎与Hibernate这款流行的Java对象关系映射(ORM)框架相结合。在这个例子中,我们将深入探讨这两个技术的集成,以及...

    Spring3 + Hibernate3 + Lucene3 + Easyui + Mysql 简单例子

    Lucene是一个全文搜索引擎库,它提供了索引和搜索文本的功能。在本例中,Lucene3可能被用来建立一个搜索引擎,便于用户对数据库中的信息进行快速检索。Lucene可以高效地处理大量文本数据,并支持多种查询语法,增强...

    struts2 + spring2.5 + hibernate 3.2 + lucene 2.4 + compass 2.0产品搜索

    struts2 + spring2.5 + hibernate 3.2 + lucene 2.4 + compass 2.0 包含所有jar包,按readme.txt导入并运行即可 开始不用分了................

    spring+hibernate3+struts2+lucene

    Lucene是一个高性能、全文本搜索引擎库,它可以被嵌入到各种应用中,用于实现复杂的搜索功能。Lucene提供了索引、查询解析、评分等功能,使得开发者能够快速构建高效的检索系统。 在这个项目中,"LuceneWeb"很可能...

    hibernate-hql-lucene-1.0.1.Final.zip

    【标题】"hibernate-hql-lucene-1.0.1.Final.zip" 提供的是一个关于Hibernate HQL与Lucene集成的开源项目版本,主要用于在Java应用程序中实现高效、复杂的全文搜索功能。 【描述】"pact-jvm.zip,pact模型" 指的是...

    J2EE博客系统 struts2+spring+hibernate+oracle+lucene

    本篇将深入探讨一个基于J2EE的博客系统,该系统采用经典的“s2sh”整合框架,即Struts2、Spring和Hibernate,以及Oracle数据库和Lucene全文搜索引擎,旨在构建高效、稳定且功能齐全的博客平台。 首先,Struts2作为...

    Hibernate搜索框架HibernateSearch.zip

    Hibernate Search主要有以下功能特点:1,功能强大,配置简单 - 配置只需要修改persistence.xml(JPA),hibernate.cfg.xml(Hibernate)2,支持Hibernate,以及EJB3 JPA标准应用3,集成全文搜索引擎Lucene - Lucene...

    Hibernate Search In Action

    通过阅读这本书,读者不仅能够学会如何使用Hibernate Search进行日常的全文搜索开发,还能够深入了解Hibernate Search的设计原理以及与底层搜索引擎Lucene之间的关系。此外,本书还探讨了全文搜索的一些高级话题,...

    Struts2.3.8整合Hibernate4.2,Spring3.2lucene 3 6 2 SSH整合1.0版

    Struts2.3.8、Hibernate4.2和Spring3.2是Java开发中的三大主流框架,它们分别负责Web层、持久层和业务层的管理,而Lucene 3.6.2则是一个强大的全文搜索引擎库。这个整合版本称为SSH整合1.0版,旨在提供一个高效、...

    Lucene与SSH2搜索功能

    "Lucene与SSH2搜索功能"的主题聚焦于如何在Java Web开发环境中利用Apache Lucene库来构建强大的搜索功能,并结合Struts2、Spring和Hibernate(简称SSH2)这三大框架进行整合。下面我们将深入探讨这些技术及其相互...

    lucene

    Lucene常与其他框架结合使用,如Spring Data Solr、Hibernate Search等,实现企业级搜索解决方案。同时,它也被用于搜索引擎开发、日志分析、推荐系统等领域。 综上所述,Lucene作为一款强大的全文搜索引擎库,其...

    使用compass+lucene实现简单的全文检索功能

    Compass 是基于 Lucene 构建的一个高级搜索引擎框架,它简化了 Lucene 的使用,并且提供了更多的特性,如自动索引、ORM 集成(Object-Relational Mapping)以及对多种持久化技术的支持,如 JPA、Hibernate 和 ...

    hibernate search全文索引的创建及查询

    在Hibernate Search中,你可以使用Lucene的查询语法或者直接使用对象查询语言(OQL)进行全文搜索。以下是一个示例: ```java FullTextSession session = Search.getFullTextSession(entityManager); session....

    Search Lucene JavaEE WebApp Struts2 Hibernate.zip

    首先,Lucene是Apache软件基金会的一个开放源代码项目,是Java语言中最为强大的全文搜索引擎库。它提供了索引和搜索文本的功能,能够高效地处理大量数据,支持复杂的查询表达式,并具有高度可定制性。在这个项目中,...

    hibernateSearch 搜索 索引列子源代码

    Hibernate Search 基于 Apache Lucene,提供了与 Hibernate ORM 集成的全文搜索引擎。它允许开发者通过注解将实体字段标记为可搜索,并在后台自动建立和更新索引。这使得开发者能够以 SQL 类似的查询方式执行复杂的...

    基于hibernate search的全文搜索引擎实现完整代码和配置文件,支持中英文

    本资源提供了基于Hibernate Search实现的全文搜索引擎的完整代码和配置文件,适用于处理中英文数据,具备拼音搜索、错误纠正和搜索建议等高级功能。 Hibernate Search是Hibernate ORM的一个扩展,它允许开发者在...

    基于Spring的Hibernate Search全文检索功能示例

    3. **Hibernate Search**:作为Hibernate的一个扩展,Hibernate Search提供了基于Lucene的全文检索功能,使得在数据库中的数据可以被快速、精确地搜索。 **二、集成Hibernate Search** 1. **配置依赖**:首先,你...

    Hibernate Search配置及简单应用

    Hibernate Search是Hibernate框架的一个扩展,它允许我们在应用程序中实现全文检索功能,使得数据库中的数据可以被快速、高效地搜索。这个功能尤其在处理大量文本数据时非常有用,比如在电商网站的商品搜索或者新闻...

Global site tag (gtag.js) - Google Analytics