lucene实际运用

原创 2007年10月08日 11:18:00

    刚结束了一个项目,回头想了下整个开发流程,决定再总结下缓存问题及lucene(全文检索)的运用。

    首先来谈下lucene

    项目的service端运用spring+hibernate开发。其间用到lucene做全文检索。版本为2.2,分词用的是JE-Analysis1.5.1.MMAnalyzer.建立索引用到队列。

   我们先在blogservice里初始化索引路径,其实现是在spring配置文件里设置:

 <bean id="blogService" class="cn.shell.service.BlogService"
  parent="baseService">
  
  <property name="indexPathRoot"
   value="${webapp.root}WEB-INF/index/blog/">
  </property>
  
</bean>

   项目中主要是要求提高性能,所以采用队列来创建索引。List  waitToIndexList=new LinkedList();

   创建索引部分:

   IndexWriter indexWriter;

   IndexSearcher indexSearcher;

   创建新线程:Thread indexThread=new Thread(this);

   实例分词:   MMAnalyzer analyzer=new MMAnalyzer();

   初始化部分:

  public void init(){

                              File rp = new File(indexPathRoot);
  if (!rp.exists()) {
   rp.mkdirs();
  }
  File segments = new File(indexPathRoot + File.separator
    + "segments.gen");
  boolean bCreate = true;
  if (segments.exists()) {
   bCreate = false;
  }
  try {
   
   indexWriter = new IndexWriter(indexPathRoot, analyzer, bCreate);
   indexSearcher = new IndexSearcher(indexPathRoot);
  } catch (Exception e) {
   logger.error("init indexWriter fail", e);
  }
  indexThread.start();                      //启动线程

}

public void run(){

while (!indexThread.isInterrupted()) {
   if (!waitToIndexList.isEmpty()) {
    Blog blog = (Blog) waitToIndexList.remove(0);
    Document doc = new Document();
    doc.add(new Field("blogID", blog.getBlogID(), Field.Store.YES,
      Field.Index.UN_TOKENIZED));
    doc.add(new Field("title", blog.getTitle(), Field.Store.YES,
      Field.Index.TOKENIZED));
    doc.add(new Field("content", blog.getContent(),
      Field.Store.YES, Field.Index.TOKENIZED));
    doc.add(new Field("author", blog.getClientUser().getNickName(),
      Field.Store.YES, Field.Index.TOKENIZED));

    try {
     indexWriter.addDocument(doc);
     indexWriter.flush();
     indexWriter.optimize();
    } catch (Exception e) {
     logger.error("create index error", e);
    }

   }

   try {
    Thread.sleep(50);
   } catch (Exception e) {
    logger.error(e);
   }

  }}

每创建一个新BLOG对象,我们将该对象塞到队列waitToIndexList中。

 public void addBlog(Blog blog) {

  AddBlogTask saveBlogTask = new AddBlogTask(blog, blogDAO);
  asyncService.doTask(saveBlogTask);
  // 更新缓存
  String k = "KEY_BLOG" + blog.getBlogID();
  cacheService.put(k, blog);

  this.waitToIndexList.add(blog);
 }

search部分:

public Hits searchBlogByLucene(String keyword){

//首先从缓存中取 看是否能取到。  

  Hits hits = (Hits) cacheService.get("BLOG_SEARCH_" + keyword);
    if (hits == null) {

    try {
    MultiFieldQueryParser queryParser = new MultiFieldQueryParser(
      new String[] { "title", "content", "author" }, analyzer);
    Query query = queryParser.parse(keyword);
    hits = indexSearcher.search(query);

   } catch (Exception e) {
    logger.error("search " + keyword, e);
   }

  //缓存中没有的情况下 再将搜到的结果塞到缓存中。
   cacheService.put("BLOG_SEARCH_" + keyword, hits);
  }
  return hits;

}//享元(flyweight)模式

 

搜索结果部分:

  public List searchBlogs(String keyword, int off, int max) {

  Hits hits = searchBlogByLucene(keyword);
  String[] ids = new String[hits.length()];
  for (int i = 0; i < hits.length(); i++) {
   Document docTemp;
   try {
    docTemp = hits.doc(i);
    String blogID = docTemp.get("blogID");
    ids[i] = blogID;
   } catch (Exception e) {

    e.printStackTrace();
   }

  }
  List hitsList = blogDAO.getBlogsByBlogIDS(ids, off, max);

  return hitsList;
 }

搜索结果集大小:

 public int getSearchBlogsCount(String keyword) {
  Hits hits = searchBlogByLucene(keyword);
  if (hits != null) {
   return hits.length();
  } else {
   return 0;
  }
 }

 

   

lucene打分公式

lucene利用余弦相似度进行计算,并进行了改进 coord(q,d):文档d匹配q的词越多,此值越大,在查询的时候计算的,匹配的词/查询的总词数(可能不一样) queryNorm(q):...
  • asd7010
  • asd7010
  • 2017年02月27日 18:04
  • 103

MySQL数据库在实际应用一些方面的介绍

此篇文章主要介绍的是MySQL数据库实际应用方面的操作。但是你必须要先登录到 MySQL数据库中,下面的操作是在MySQL数据库的实际提示符之下进行的,同时也要求每个相关命令以分号结束。     一...
  • u012315717
  • u012315717
  • 2013年12月25日 22:23
  • 1284

论算法的实际应用——泡妞论

我们都知道,算法,即解决问题的方法,我们衡量一个算法的优劣,可以用空间复杂度与时间复杂度来衡量。 换做我们实际生活中,就是物质成本开销与时间成本开销。 不同算法进行泡妞这一业务进行其物质成本开销与时间...
  • sm9sun
  • sm9sun
  • 2016年12月08日 17:27
  • 414

20种常用的DOS命令小结

先介绍一下通配符的概念。 通配符*和? *表示一个字符串 ?只代表一个字符 注意通配符只能通配文件名或扩展名,不能全都表示。例如我们要查找以字母y开头的所有文件,可以输...
  • hwhua1986
  • hwhua1986
  • 2015年08月18日 21:53
  • 1127

Runloop 实际应用和详细解释

上篇文章讲了Runloop的基本原理和一些需要注意的事项,那今天来说一下Runloop在实际开发中的一些应用场景和更深刻的理解。大家都知道我们开Timer就会出现耗时操作,那么呢耗时操作肯定不能在主线...
  • cuzzZYues
  • cuzzZYues
  • 2017年06月01日 10:36
  • 187

shiro学习摘录(二)

shiro学习小记(二)Shiro内置拦截器。默认拦截器可参考org.apache.shiro.web.filter.mgt.DefaultFilter中的枚举拦截器。 默认拦截器名 拦截器类...
  • jackieJay
  • jackieJay
  • 2016年03月30日 18:34
  • 380

Lucene实例(各种Query使用的例子)

在网上看了许多相关的例子,很杂很琐碎,在这里贴出一些源代码,感觉还不错的,介绍了各种Query子类的使用:     创建索引:   package example.lucene; im...
  • zeq9069
  • zeq9069
  • 2013年11月18日 17:48
  • 2823

JavaWeb项目:整合(Lucene+Redis+SSM)实现搜索功能

整体思路:使用Redis做缓存,缓存策略为首次查询从数据库抓取,取出后存入Redis(有效期为48h),删除和更新操作在Redis中进行,并且定时同步至数据库;Lucene做全文检索,RAMDirec...
  • CrazyLai1996
  • CrazyLai1996
  • 2017年08月05日 20:56
  • 1464

runtime从入门到精通(六)—— runtime在实际开发中的应用

上一篇文章,我们学习了runtime的消息发送和消息转发机制(查看链接: runtime从入门到精通(五)—— 消息发送和消息转发 ),倒到此为止,有关runtime的理论知识介绍就先告于段落,小伙伴...
  • coyote1994
  • coyote1994
  • 2016年09月08日 12:08
  • 2110

初学linux并在项目中的实际应用

1,首先下载一个小工具,链接linux。
  • u012138706
  • u012138706
  • 2014年08月22日 14:28
  • 1219
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:lucene实际运用
举报原因:
原因补充:

(最多只允许输入30个字)