hibernate search 和lucene结合使用实例

以下的代码是根据api帮助文档作出的一个简单实例,在应用方面可以实现创建索引,搜索,过滤和高亮的功能。

整体的环境为:spring2.5.6,hibernate3.3.1,struts2.0.8,lucene2.4.1

第一步,首先是web.xml配置文件,由于使用了ssh2的架构,所以不得不在web.xml里配置一些东西

Java代码 复制代码
  1. ]<?xml version="1.0" encoding="UTF-8"?>   
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee    
  5.  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">   
  6.   
  7.  <!-- spring的配置文件路径 -->   
  8.  <context-param>   
  9.   <param-name>contextConfigLocation</param-name>   
  10.   <param-value>classpath*:spring/*.xml</param-value>   
  11.  </context-param>   
  12.     
  13.  <!--Hibernate Open Session in View Filter-->   
  14.  <filter>   
  15.   <filter-name>hibernateFilter</filter-name>   
  16.   <filter-class>   
  17.    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter   
  18.   </filter-class>   
  19.  </filter>   
  20.  <filter-mapping>   
  21.   <filter-name>hibernateFilter</filter-name>   
  22.   <url-pattern>*.action</url-pattern>   
  23.   <dispatcher>REQUEST</dispatcher>   
  24.   <dispatcher>FORWARD</dispatcher>   
  25.  </filter-mapping>   
  26.  <filter-mapping>   
  27.   <filter-name>hibernateFilter</filter-name>   
  28.   <url-pattern>*.jsp</url-pattern>   
  29.   <dispatcher>REQUEST</dispatcher>   
  30.   <dispatcher>FORWARD</dispatcher>   
  31.  </filter-mapping>   
  32.     
  33.  <listener>   
  34.   <listener-class>   
  35.    org.springframework.web.context.ContextLoaderListener   
  36.   </listener-class>   
  37.  </listener>   
  38.   
  39.  <!-- Spring 刷新Introspector防止内存泄露 -->   
  40.  <listener>   
  41.   <listener-class>   
  42.    org.springframework.web.util.IntrospectorCleanupListener   
  43.   </listener-class>   
  44.  </listener>   
  45.   
  46.  <!-- Struts Action Mapping-->   
  47.  <filter>   
  48.   <filter-name>struts-cleanup</filter-name>   
  49.   <filter-class>   
  50.    org.apache.struts2.dispatcher.ActionContextCleanUp   
  51.   </filter-class>   
  52.  </filter>   
  53.  <filter>   
  54.   <filter-name>struts2</filter-name>   
  55.   <filter-class>   
  56.    org.apache.struts2.dispatcher.FilterDispatcher   
  57.   </filter-class>   
  58.  </filter>   
  59.   
  60.  <filter-mapping>   
  61.   <filter-name>struts-cleanup</filter-name>   
  62.   <url-pattern>/*</url-pattern>   
  63.  </filter-mapping>    
  64.  <filter-mapping>   
  65.   <filter-name>struts2</filter-name>   
  66.   <url-pattern>*.jsp</url-pattern>   
  67.   <dispatcher>REQUEST</dispatcher>   
  68.   <dispatcher>FORWARD</dispatcher>   
  69.  </filter-mapping>   
  70.  <filter-mapping>   
  71.   <filter-name>struts2</filter-name>   
  72.   <url-pattern>*.action</url-pattern>   
  73.   <dispatcher>REQUEST</dispatcher>   
  74.   <dispatcher>FORWARD</dispatcher>   
  75.  </filter-mapping>   
  76.   
  77. <!-- spring自带的字符转换过滤器,转换成utf-8的格式 -->   
  78.  <filter>   
  79.   <filter-name>encodingFilter</filter-name>   
  80.   <filter-class>   
  81.    org.springframework.web.filter.CharacterEncodingFilter   
  82.   </filter-class>   
  83.   <init-param>   
  84.    <param-name>encoding</param-name>   
  85.    <param-value>UTF-8</param-value>   
  86.   </init-param>   
  87.  </filter>   
  88.  <filter-mapping>   
  89.   <filter-name>encodingFilter</filter-name>   
  90.   <url-pattern>/*</url-pattern>   
  91.  </filter-mapping>   
  92.   
  93.  <!-- 随服务器启动,自动调用对应的servlet创建索引文件 -->   
  94.   
  95.  <servlet>   
  96.   <servlet-name>CreateHibernateIndex</servlet-name>   
  97.   <servlet-class>com.test.servlet.CreateHibernateIndex</servlet-class>   
  98.   <load-on-startup>20</load-on-startup>   
  99.  </servlet>   
  100.  <servlet-mapping>   
  101.   <servlet-name>CreateHibernateIndex</servlet-name>   
  102.   <url-pattern>/servlet/CreateHibernateIndex</url-pattern>   
  103.  </servlet-mapping>   
  104.   
  105.  <!-- session超时定义,单位为分钟 -->   
  106.  <session-config>   
  107.   <session-timeout>20</session-timeout>   
  108.  </session-config>   
  109.  <!-- 默认首页定义 -->   
  110.  <welcome-file-list>   
  111.   <welcome-file>/index.jsp</welcome-file>   
  112.  </welcome-file-list>   
  113.   
  114. </web-app>  
]<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- spring的配置文件路径 --> <context-param>  <param-name>contextConfigLocation</param-name>  <param-value>classpath*:spring/*.xml</param-value> </context-param>  <!--Hibernate Open Session in View Filter--> <filter>  <filter-name>hibernateFilter</filter-name>  <filter-class>   org.springframework.orm.hibernate3.support.OpenSessionInViewFilter  </filter-class> </filter> <filter-mapping>  <filter-name>hibernateFilter</filter-name>  <url-pattern>*.action</url-pattern>  <dispatcher>REQUEST</dispatcher>  <dispatcher>FORWARD</dispatcher> </filter-mapping> <filter-mapping>  <filter-name>hibernateFilter</filter-name>  <url-pattern>*.jsp</url-pattern>  <dispatcher>REQUEST</dispatcher>  <dispatcher>FORWARD</dispatcher> </filter-mapping>  <listener>  <listener-class>   org.springframework.web.context.ContextLoaderListener  </listener-class> </listener> <!-- Spring 刷新Introspector防止内存泄露 --> <listener>  <listener-class>   org.springframework.web.util.IntrospectorCleanupListener  </listener-class> </listener> <!-- Struts Action Mapping--> <filter>  <filter-name>struts-cleanup</filter-name>  <filter-class>   org.apache.struts2.dispatcher.ActionContextCleanUp  </filter-class> </filter> <filter>  <filter-name>struts2</filter-name>  <filter-class>   org.apache.struts2.dispatcher.FilterDispatcher  </filter-class> </filter> <filter-mapping>  <filter-name>struts-cleanup</filter-name>  <url-pattern>/*</url-pattern> </filter-mapping>  <filter-mapping>  <filter-name>struts2</filter-name>  <url-pattern>*.jsp</url-pattern>  <dispatcher>REQUEST</dispatcher>  <dispatcher>FORWARD</dispatcher> </filter-mapping> <filter-mapping>  <filter-name>struts2</filter-name>  <url-pattern>*.action</url-pattern>  <dispatcher>REQUEST</dispatcher>  <dispatcher>FORWARD</dispatcher> </filter-mapping><!-- spring自带的字符转换过滤器,转换成utf-8的格式 --> <filter>  <filter-name>encodingFilter</filter-name>  <filter-class>   org.springframework.web.filter.CharacterEncodingFilter  </filter-class>  <init-param>   <param-name>encoding</param-name>   <param-value>UTF-8</param-value>  </init-param> </filter> <filter-mapping>  <filter-name>encodingFilter</filter-name>  <url-pattern>/*</url-pattern> </filter-mapping> <!-- 随服务器启动,自动调用对应的servlet创建索引文件 --> <servlet>  <servlet-name>CreateHibernateIndex</servlet-name>  <servlet-class>com.test.servlet.CreateHibernateIndex</servlet-class>  <load-on-startup>20</load-on-startup> </servlet> <servlet-mapping>  <servlet-name>CreateHibernateIndex</servlet-name>  <url-pattern>/servlet/CreateHibernateIndex</url-pattern> </servlet-mapping> <!-- session超时定义,单位为分钟 --> <session-config>  <session-timeout>20</session-timeout> </session-config> <!-- 默认首页定义 --> <welcome-file-list>  <welcome-file>/index.jsp</welcome-file> </welcome-file-list></web-app>


第二步,配spring配置文件和hibernate文件

这是可以使用hibernate annotation注释的sessionFactory的属性配置的一部分,注意下面的2个使用索引的属性配置,提供文件索引的保存路径和读取方式(fsdirectory,文件索引,另外一种是ramdirectory,内存索引)

Java代码 复制代码
  1. <prop   
  2.      key="hibernate.search.default.directory_provider">   
  3.      org.hibernate.search.store.FSDirectoryProvider   
  4.     </prop>   
  5.     <prop key="hibernate.search.default.indexBase">   
  6.      ${hibernate.search.default.indexBase}   
  7.     </prop>  
<prop     key="hibernate.search.default.directory_provider">     org.hibernate.search.store.FSDirectoryProvider    </prop>    <prop key="hibernate.search.default.indexBase">     ${hibernate.search.default.indexBase}    </prop>


   
spring的配置文件没有什么特别的,和普通ssh配置没有什么两样

第三步配struts配置文件,由于也是普通配置,没有特别之处,就不贴出来了。

第四步,写实体类,由于采用hibernate search方法搜索,所以直接利用hibernate annotation注释去定义索引的一些配置信息。关于index的基本都属于索引的配置

Java代码 复制代码
  1. package com.test.model;   
  2.   
  3. import static javax.persistence.GenerationType.IDENTITY;   
  4.   
  5. import java.util.Date;   
  6.   
  7. import javax.persistence.Column;   
  8. import javax.persistence.Entity;   
  9. import javax.persistence.GeneratedValue;   
  10. import javax.persistence.Id;   
  11. import javax.persistence.Table;   
  12. import javax.persistence.Temporal;   
  13. import javax.persistence.TemporalType;   
  14. import javax.persistence.Transient;   
  15.   
  16. import org.hibernate.search.annotations.Analyzer;   
  17. import org.hibernate.search.annotations.DateBridge;   
  18. import org.hibernate.search.annotations.DocumentId;   
  19. import org.hibernate.search.annotations.Field;   
  20. import org.hibernate.search.annotations.Index;   
  21. import org.hibernate.search.annotations.Indexed;   
  22. import org.hibernate.search.annotations.Resolution;   
  23. import org.hibernate.search.annotations.Store;   
  24. import org.wltea.analyzer.lucene.IKAnalyzer;   
  25.   
  26.   
  27. /**  
  28.  * Product entity.  
  29.  */  
  30. @Entity  
  31. @Table(name = "product", catalog = "hibernate_search_test")   
  32. @Indexed(index = "Product")   
  33. @Analyzer (impl = IKAnalyzer.class )    
  34. public class Product implements java.io.Serializable {   
  35.   
  36.  // Fields   
  37.   
  38.  /**  
  39.   *   
  40.   */  
  41.  private static final long serialVersionUID = -7005490272739421758L;   
  42.  private Integer id;   
  43.  private String proTitle;   
  44.  private String proDescn;   
  45.  private String proPrice;   
  46.  private Integer proType;   
  47.  private Date proTime;   
  48.  private String findResult;   
  49.   
  50.  // Constructors   
  51.   
  52.  /** default constructor */  
  53.  public Product() {   
  54.  }   
  55.   
  56.  // Property accessors   
  57.  @Id  
  58.  @GeneratedValue(strategy = IDENTITY)   
  59.  @Column(name = "id")   
  60.  @DocumentId    
  61.  public Integer getId() {   
  62.   return this.id;   
  63.  }   
  64.   
  65.  public void setId(Integer id) {   
  66.   this.id = id;   
  67.  }   
  68.   
  69.  @Column(name = "pro_title")   
  70.  @Field(name = "pt", index = Index.TOKENIZED, store = Store.YES)   
  71.  public String getProTitle() {   
  72.   return this.proTitle;   
  73.  }   
  74.   
  75.  public void setProTitle(String proTitle) {   
  76.   this.proTitle = proTitle;   
  77.  }   
  78.   
  79.  @Column(name = "pro_descn")   
  80.  @Field(name = "pd", index = Index.TOKENIZED, store = Store.YES)   
  81.  public String getProDescn() {   
  82.   return this.proDescn;   
  83.  }   
  84.   
  85.  public void setProDescn(String proDescn) {   
  86.   this.proDescn = proDescn;   
  87.  }   
  88.   
  89.  @Column(name = "pro_price")   
  90.  public String getProPrice() {   
  91.   return this.proPrice;   
  92.  }   
  93.   
  94.  public void setProPrice(String proPrice) {   
  95.   this.proPrice = proPrice;   
  96.  }   
  97.   
  98.  @Column(name = "pro_type")   
  99.  public Integer getProType() {   
  100.   return this.proType;   
  101.  }   
  102.   
  103.  public void setProType(Integer proType) {   
  104.   this.proType = proType;   
  105.  }   
  106.   
  107.  @Temporal(TemporalType.DATE)   
  108.  @Column(name = "pro_time")   
  109.  @Field(name = "t", index = Index.UN_TOKENIZED, store = Store.YES)   
  110.  @DateBridge(resolution = Resolution.DAY)   
  111.  public Date getProTime() {   
  112.   return this.proTime;   
  113.  }   
  114.   
  115.  public void setProTime(Date proTime) {   
  116.   this.proTime = proTime;   
  117.  }   
  118.   
  119. //封装搜索出的高亮内容   
  120.  @Transient  
  121.  public String getFindResult() {   
  122.   return findResult;   
  123.  }   
  124.   
  125.  public void setFindResult(String findResult) {   
  126.   this.findResult = findResult;   
  127.  }   
  128. }  
package com.test.model;import static javax.persistence.GenerationType.IDENTITY;import java.util.Date;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.Id;import javax.persistence.Table;import javax.persistence.Temporal;import javax.persistence.TemporalType;import javax.persistence.Transient;import org.hibernate.search.annotations.Analyzer;import org.hibernate.search.annotations.DateBridge;import org.hibernate.search.annotations.DocumentId;import org.hibernate.search.annotations.Field;import org.hibernate.search.annotations.Index;import org.hibernate.search.annotations.Indexed;import org.hibernate.search.annotations.Resolution;import org.hibernate.search.annotations.Store;import org.wltea.analyzer.lucene.IKAnalyzer;/** * Product entity. */@Entity@Table(name = "product", catalog = "hibernate_search_test")@Indexed(index = "Product")@Analyzer (impl = IKAnalyzer.class ) public class Product implements java.io.Serializable { // Fields /**  *   */ private static final long serialVersionUID = -7005490272739421758L; private Integer id; private String proTitle; private String proDescn; private String proPrice; private Integer proType; private Date proTime; private String findResult; // Constructors /** default constructor */ public Product() { } // Property accessors @Id @GeneratedValue(strategy = IDENTITY) @Column(name = "id") @DocumentId  public Integer getId() {  return this.id; } public void setId(Integer id) {  this.id = id; } @Column(name = "pro_title") @Field(name = "pt", index = Index.TOKENIZED, store = Store.YES) public String getProTitle() {  return this.proTitle; } public void setProTitle(String proTitle) {  this.proTitle = proTitle; } @Column(name = "pro_descn") @Field(name = "pd", index = Index.TOKENIZED, store = Store.YES) public String getProDescn() {  return this.proDescn; } public void setProDescn(String proDescn) {  this.proDescn = proDescn; } @Column(name = "pro_price") public String getProPrice() {  return this.proPrice; } public void setProPrice(String proPrice) {  this.proPrice = proPrice; } @Column(name = "pro_type") public Integer getProType() {  return this.proType; } public void setProType(Integer proType) {  this.proType = proType; } @Temporal(TemporalType.DATE) @Column(name = "pro_time") @Field(name = "t", index = Index.UN_TOKENIZED, store = Store.YES) @DateBridge(resolution = Resolution.DAY) public Date getProTime() {  return this.proTime; } public void setProTime(Date proTime) {  this.proTime = proTime; }//封装搜索出的高亮内容 @Transient public String getFindResult() {  return findResult; } public void setFindResult(String findResult) {  this.findResult = findResult; }}


第六步,写service方法,包括建索引,根据关键字用索引查,过滤,设置权重,高亮等等工作

Java代码 复制代码
  1. package com.test.service;   
  2.   
  3. import java.io.File;   
  4. import java.io.StringReader;   
  5. import java.util.Date;   
  6. import java.util.List;   
  7.   
  8. import javax.annotation.Resource;   
  9.   
  10. import org.apache.lucene.analysis.Analyzer;   
  11. import org.apache.lucene.analysis.Token;   
  12. import org.apache.lucene.analysis.TokenStream;   
  13. import org.apache.lucene.document.DateTools;   
  14. import org.apache.lucene.document.Document;   
  15. import org.apache.lucene.document.Field;   
  16. import org.apache.lucene.document.DateTools.Resolution;   
  17. import org.apache.lucene.index.IndexReader;   
  18. import org.apache.lucene.index.IndexWriter;   
  19. import org.apache.lucene.index.Term;   
  20. import org.apache.lucene.queryParser.QueryParser;   
  21. import org.apache.lucene.search.BooleanClause;   
  22. import org.apache.lucene.search.BooleanQuery;   
  23. import org.apache.lucene.search.CachingWrapperFilter;   
  24. import org.apache.lucene.search.Filter;   
  25. import org.apache.lucene.search.IndexSearcher;   
  26. import org.apache.lucene.search.Query;   
  27. import org.apache.lucene.search.QueryWrapperFilter;   
  28. import org.apache.lucene.search.ScoreDoc;   
  29. import org.apache.lucene.search.TermQuery;   
  30. import org.apache.lucene.search.TermRangeQuery;   
  31. import org.apache.lucene.search.TopScoreDocCollector;   
  32. import org.apache.lucene.search.BooleanClause.Occur;   
  33. import org.apache.lucene.search.highlight.Formatter;   
  34. import org.apache.lucene.search.highlight.Highlighter;   
  35. import org.apache.lucene.search.highlight.QueryScorer;   
  36. import org.apache.lucene.search.highlight.SimpleFragmenter;   
  37. import org.apache.lucene.search.highlight.SimpleHTMLFormatter;   
  38. import org.apache.lucene.store.FSDirectory;   
  39. import org.apache.lucene.util.Version;   
  40. import org.hibernate.CacheMode;   
  41. import org.hibernate.FlushMode;   
  42. import org.hibernate.ScrollMode;   
  43. import org.hibernate.ScrollableResults;   
  44. import org.hibernate.search.FullTextQuery;   
  45. import org.hibernate.search.FullTextSession;   
  46. import org.hibernate.search.Search;   
  47. import org.springframework.context.ApplicationContext;   
  48. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  49. import org.springframework.stereotype.Service;   
  50. import org.springframework.transaction.annotation.Transactional;   
  51. import org.springside.modules.orm.hibernate.HibernateDao;   
  52. import org.springside.modules.service.EntityManager;   
  53. import org.wltea.analyzer.lucene.IKAnalyzer;   
  54.   
  55. import com.test.dao.ProductDao;   
  56. import com.test.model.Product;   
  57.   
  58. @Transactional  
  59. @Service  
  60. public class ProductService extends EntityManager<Product, Integer> {   
  61.  @Resource(name = "productDao")   
  62.  private ProductDao productDao;   
  63.   
  64.  @Override  
  65.  protected HibernateDao<Product, Integer> getEntityDao() {   
  66.   // TODO Auto-generated method stub   
  67.   return productDao;   
  68.  }   
  69.   
  70.  @SuppressWarnings("unchecked")   
  71.  public List<Product> QueryByIndex(String words, String startDate,String endDate) throws Exception {   
  72.   FullTextSession fullTextSession = Search.createFullTextSession(productDao.getSession());   
  73.   
  74.   /*Query IKQuery = IKQueryParser.parseMultiField(new String[] {  
  75.     "proTitle", "proDescn" }, new String[] { words, words },  
  76.     new BooleanClause.Occur[] { Occur.SHOULD, Occur.SHOULD });  
  77.  
  78.   Query luceneQuery = MultiFieldQueryParser.parse(new String[] { words,  
  79.     words }, new String[] { "pro_title", "pro_descn" },  
  80.     new BooleanClause.Occur[] { Occur.SHOULD, Occur.SHOULD },  
  81.     new StandardAnalyzer());*/  
  82.   BooleanQuery bQuery = new BooleanQuery();   
  83.   Analyzer analyzer = new IKAnalyzer();   
  84.   //设置对域采用的某种分词器的QueryParser对象   
  85.   QueryParser qp;   
  86.   //设置了关键字的查询您对象   
  87.   //Query q;   
  88.      
  89.   qp = new QueryParser(Version.LUCENE_CURRENT,"pt",analyzer);   
  90.   Query q1 = qp.parse(words);   
  91.   q1.setBoost(1.5f);   
  92.   bQuery.add(q1, Occur.SHOULD);   
  93.      
  94.   qp = new QueryParser(Version.LUCENE_CURRENT,"pd",analyzer);   
  95.   Query q2 = qp.parse(words);   
  96.   q2.setBoost(1.0f);   
  97.   bQuery.add(q2, Occur.SHOULD);   
  98.      
  99.   FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(bQuery,Product.class);   
  100.   // 添加是或者否的条件到query中   
  101.   boolean filterResult = false;   
  102.   BooleanQuery bQueryForFilter = new BooleanQuery();   
  103.   
  104.   if (!startDate.equalsIgnoreCase("") && !endDate.equalsIgnoreCase("")) {   
  105.    // 时间过滤   
  106.    // RangeFilter rangefilter = new RangeFilter("pro_time",   
  107.    // "20090927","20090929", false, false);   
  108.    // 只能使用一个过滤器,所以只能用下面的RangeQuery,然后将所有query封装到一个过滤条件中   
  109.    TermRangeQuery rangeQuery = new TermRangeQuery("t",startDate,endDate,true,true);   
  110.    bQueryForFilter.add(rangeQuery, BooleanClause.Occur.MUST);   
  111.    filterResult = true;   
  112.   }   
  113.   if (filterResult) {   
  114.    // 将booleanQuery封装到Filter中   
  115.    Filter filter = new CachingWrapperFilter(new QueryWrapperFilter(bQueryForFilter));   
  116.    fullTextQuery.setFilter(filter);   
  117.   }   
  118.      
  119.   List<Product> result = fullTextQuery.list();   
  120.   String findResult;   
  121.   
  122. //根据上边已经写好的query封装出一个查询计分器   
  123.   QueryScorer qs1 = new QueryScorer(q1);   
  124.   QueryScorer qs2 = new QueryScorer(q2);   
  125.   //设置高亮的模板,其实就是在关键字两边加一对html的格式标签,下面是最基本的加粗。   
  126.   Formatter formatter = new SimpleHTMLFormatter("<b>""</b>");   
  127.      
  128.   Highlighter highlighter1 = new Highlighter(formatter,qs1);   
  129.   Highlighter highlighter2 = new Highlighter(formatter,qs2);   
  130.   String text;   
  131.   
  132. //下面通过将上面根据关键字,过滤条件和权重排序等找出的结果集做一次循环,进行高亮,把高亮后得到的   
  133.   
  134. //一个字符串,封装如每个实体类中的一个额外字段,方便在页面输出。   
  135.   for(Product product:result){   
  136.    text = product.getProTitle() ;   
  137.    findResult = highlighter1.getBestFragment(analyzer,"pt", text);   
  138.    if(findResult==null){   
  139.     text = product.getProDescn() ;   
  140.     highlighter2.setTextFragmenter(new SimpleFragmenter(30));   
  141.     findResult = highlighter2.getBestFragment(analyzer,"pd", text);   
  142.    }   
  143.    product.setFindResult(findResult);   
  144.   }     
  145.   return result;   
  146.  }   
  147.   
  148. //下面的方法是用hibernate search的方法来创建索引   
  149.   
  150.  public void createIndexByHibernateSearch() {   
  151.   
  152.   long startTime = new Date().getTime();   
  153.   int BATCH_SIZE = 1000;   
  154.   FullTextSession s = Search.createFullTextSession(productDao.getSession());   
  155.   
  156.   // Transaction tr = s.beginTransaction();   
  157.   s.setFlushMode(FlushMode.MANUAL);   
  158.   s.setCacheMode(CacheMode.IGNORE);   
  159.   ScrollableResults results = s.createQuery("from Product").setFetchSize(BATCH_SIZE).scroll(ScrollMode.FORWARD_ONLY);   
  160.   int index = 0;   
  161.   while (results.next()) {   
  162.    index++;   
  163.    s.index(results.get(0)); // index each element   
  164.    if (index % BATCH_SIZE == 0) {   
  165.     // s.flushToIndexes(); //apply changes to indexes   
  166.     s.clear(); // clear since the queue is processed   
  167.    }   
  168.   }   
  169.   s.clear();   
  170.   long endTime = new Date().getTime();   
  171.   logger.warn("建立Product索引 , 这花费了" + (endTime - startTime) + " 毫秒来把文档增加到索引里面去!");   
  172.   // tr.commit();   
  173.   
  174.  }   
  175.   
  176. //下面的方法是用lucene的方式来创建索引文件,不过用这种方式创建索引后,也只能使用lucene的方式去进行搜索   
  177.   
  178.  @SuppressWarnings("deprecation")   
  179.  public void createIndexByLucene() {   
  180.   try {   
  181.    File fsDir = new File("E:\\indexes\\product");   
  182.    Analyzer analyzer = new IKAnalyzer();   
  183.   
  184.       
  185.    /* // 内存索引  
  186.       RAMDirectory ramDir = new RAMDirectory();  
  187.    IndexWriter ramWriter = new IndexWriter(ramDir, luceneAnalyzer,  
  188.      true, IndexWriter.MaxFieldLength.UNLIMITED);  
  189.    */  
  190.    IndexWriter fsWriter = new IndexWriter(   
  191.      FSDirectory.open(fsDir),   
  192.      analyzer,   
  193.      true,   
  194.      IndexWriter.MaxFieldLength.UNLIMITED   
  195.     );   
  196.    fsWriter.setMaxBufferedDocs(1000);   
  197.    fsWriter.setMergeFactor(1000);   
  198.   
  199.    List<Product> productList = find("from Product");   
  200.    int size = productList.size();   
  201.    long startTime = new Date().getTime();   
  202.    Document doc;   
  203.    for (Product product : productList) {   
  204.     doc = new Document();   
  205.     doc.add(new Field("pro_title", product.getProTitle(),Field.Store.YES, Field.Index.ANALYZED));   
  206.     doc.add(new Field("pro_descn", product.getProDescn(),Field.Store.YES, Field.Index.ANALYZED));   
  207.     if(product.getProTime()!=null)   
  208.     doc.add(new Field("pro_time",DateTools.dateToString( product.getProTime(), Resolution.DAY),Field.Store.YES, Field.Index.NOT_ANALYZED));   
  209.     fsWriter.addDocument(doc);   
  210.   
  211.     // 先缓存入内存索引,后写入文件索引   
  212.    /* ramWriter.addDocument(doc);  
  213.     int i = 1;  
  214.     i++;  
  215.     if (i % 100 == 0 || i == size) {  
  216.      logger.warn("i:" + i);  
  217.      ramWriter.close();  
  218.      fsWriter.addIndexesNoOptimize(new Directory[] { ramDir });  
  219.      ramWriter = new IndexWriter(ramDir, new StandardAnalyzer(),  
  220.        true, IndexWriter.MaxFieldLength.UNLIMITED);  
  221.     }*/  
  222.   
  223.    }   
  224.    // 自动优化合并索引文件   
  225.    fsWriter.optimize();   
  226.    fsWriter.close();   
  227.   
  228.    long endTime = new Date().getTime();   
  229.    System.out.println("一共" + size + ",这花费了" + (endTime - startTime)   
  230.      + " 毫秒来把文档增加到索引里面去!");   
  231.       
  232.   
  233.   } catch (Exception e) {   
  234.    e.printStackTrace();   
  235.   }   
  236.  }   
  237.     
  238.  public void SearchByLucene(){   
  239.   createIndexByLucene();   
  240.   File fsDir = new File("E:\\luceneIndexes\\product");   
  241.   Analyzer analyzer = new IKAnalyzer();   
  242.   try{   
  243.    // 索引查询   
  244.    IndexReader reader = IndexReader.open(FSDirectory.open(fsDir), true); // only searching, so read-only=true   
  245.    IndexSearcher isearcher = new IndexSearcher(reader);   
  246.       
  247.    BooleanQuery booleanQuery = new BooleanQuery();   
  248.    QueryParser parser;   
  249.    Query query;   
  250.       
  251.    parser = new QueryParser(Version.LUCENE_CURRENT,"pro_title",analyzer);   
  252.    query = parser.parse("大灯");// 检索词   
  253.    query.setBoost(1.5f);   
  254.    booleanQuery.add(query, Occur.SHOULD);   
  255.       
  256.    parser = new QueryParser(Version.LUCENE_CURRENT,"pro_descn",analyzer);      
  257.    query = parser.parse("大灯");// 检索词   
  258.    query.setBoost(1.0f);   
  259.    booleanQuery.add(query, Occur.SHOULD);   
  260.       
  261.    BooleanQuery filterBooleanQuery = new BooleanQuery();   
  262.    TermRangeQuery rangeQuery = new TermRangeQuery("pro_time","20090101","20091101",true,true);   
  263.    filterBooleanQuery.add(rangeQuery, BooleanClause.Occur.MUST);   
  264.       
  265.    // 将booleanQuery封装到Filter中   
  266.    Filter filter = new CachingWrapperFilter(new QueryWrapperFilter(filterBooleanQuery));   
  267.       
  268.    TopScoreDocCollector collector = TopScoreDocCollector.create(100,true);       
  269.       
  270.    isearcher.search(booleanQuery,filter,collector);   
  271.       
  272.    ScoreDoc[] hits = collector.topDocs(0,100).scoreDocs;   
  273.    QueryScorer qs = new QueryScorer(new TermQuery(new Term("pro_title","大灯")));   
  274.       
  275.    for(ScoreDoc h:hits){   
  276.     Document d = isearcher.doc(h.doc);   
  277.     String text = d.get("pro_title") ;   
  278.     Formatter formatter = new SimpleHTMLFormatter("<b>""</b>");    
  279.        
  280.     Highlighter hl = new Highlighter(formatter,qs);   
  281.        
  282.     System.out.println(hl.getBestFragment(analyzer,"pro_title", text));   
  283.     //System.out.println("doc:"+h.doc+"  \tscore:"+h.score+"      \t"+d.get("pro_title"));   
  284.    }   
  285.    System.out.println("命中:" + hits.length);   
  286.    isearcher.close();   
  287.       
  288.   }catch(Exception e){   
  289.    e.printStackTrace();   
  290.   }   
  291.      
  292.  }   
  293.   
  294.  // 查看分词效果   
  295.  @SuppressWarnings("deprecation")   
  296.  public static void showAnalyzerResult(Analyzer analyzer, String s)   
  297.    throws Exception {   
  298.   StringReader reader = new StringReader(s);   
  299.   TokenStream ts = analyzer.tokenStream(s, reader);   
  300.   Token t = ts.next();   
  301.   while (t != null) {   
  302.    System.out.print(t.termText() + "   ");   
  303.    t = ts.next();   
  304.   }   
  305.   System.out.println();   
  306.  }   
  307.   
  308.  public static void main(String[] args) {   
  309.   ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/applicationContext.xml");   
  310.   ProductService service = (ProductService) ctx.getBean("productService");   
  311.   
  312.   service.SearchByLucene();   
  313.   
  314.  }   
  315. }  
posted @ 2010-11-09 11:20  七郎  Views(7168)  Comments(0Edit  收藏  举报