全文检索Lucene的第一次尝试

本文介绍了一种利用Lucene进行全文检索的方法,包括索引创建、模糊搜索及精确查询等功能实现,并分享了实际应用中的一些心得。

由于系统搜索速度一直不理想,今天决定用Lucene进行 索引。然后全表检索 核心代码如下

 
package net.java2000.forum.util;

import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.sql.DataSource;
import org.apache.lucene.analysis.Analyzer;
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;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
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.WildcardQuery;
/**
 * 
 * @author 赵学庆 www.java2000.net
 *
 */
public class Lucene {
  private static final String indexPath = "d:/index/www.java2000.net";

  /**
   * @param args
   * @throws Exception
   */
  public static void main(String[] args) throws Exception {
    // create();
    Lucene l = new Lucene();
    System.out.println("模糊搜索/n------------------------------");
    l.seacherWildcard("域名");
    System.out.println("索引搜索/n------------------------------");
    l.seacherIndex("域名 AND 系统");
  }

  public static void rebuildAll() {
    synchronized (indexPath) {
      Lucene l = new Lucene();
      DataSource ds = (DataSource) Factory.getBean("dataSource");
      Connection con = null;
      Statement stat = null;
      ResultSet rs = null;
      try {
        con = ds.getConnection();
        stat = con.createStatement();
        rs = stat.executeQuery("select id,subject,content from t_post");
        if (rs != null) {
          l.Index(rs);
        }
      } catch (Exception ex) {
        ex.printStackTrace();
      } finally {
        if (rs != null) {
          try {
            rs.close();
          } catch (Exception ex) {}
        }
        if (stat != null) {
          try {
            stat.close();
          } catch (Exception ex) {}
        }
        if (con != null) {
          try {
            con.close();
          } catch (Exception ex) {}
        }
      }
    }
  }

  public synchronized Analyzer getAnalyzer() {
    return new StandardAnalyzer();
  }

  private synchronized void Index(ResultSet rs) {// 通过结果集就可以获得数据源了
    try {
      IndexWriter writer = new IndexWriter(indexPath, getAnalyzer(), true);
      Date start = new Date();
      while (rs.next()) {
        Document doc = new Document();// 一个文档相当与表的一条记录
        doc.add(new Field("id", rs.getString("id"), Field.Store.YES, Field.Index.UN_TOKENIZED));// 字段id放的是数据库表中的id,lucene的一条记录的一个字段下的数据可以放多个值,这点与数据库表不同
        doc.add(new Field("subject", rs.getString("subject"), Field.Store.YES, Field.Index.TOKENIZED));
        doc.add(new Field("content", rs.getString("content"), Field.Store.YES, Field.Index.TOKENIZED));
        writer.addDocument(doc);
      }
      writer.optimize();// 优化
      writer.close();// 一定要关闭,否则不能把内存中的数据写到文件
      Date end = new Date();
      System.out.println("重建索引成功!!!!" + "用时" + (end.getTime() - start.getTime()) + "毫秒");
    } catch (IOException e) {
      System.out.println(e);
    } catch (SQLException e) {
      System.out.println(e);
    }
  }

  public void IndexSingle(long id, String subject, String content) {// 通过结果集就可以获得数据源了
    synchronized (indexPath) {
      try {
        IndexWriter writer = new IndexWriter(indexPath, getAnalyzer(), false);
        Date start = new Date();
        Document doc = new Document();// 一个文档相当与表的一条记录
        doc.add(new Field("id", Long.toString(id), Field.Store.YES, Field.Index.UN_TOKENIZED));// 字段id放的是数据库表中的id,lucene的一条记录的一个字段下的数据可以放多个值,这点与数据库表不同
        doc.add(new Field("subject", subject, Field.Store.YES, Field.Index.TOKENIZED));
        doc.add(new Field("content", content, Field.Store.YES, Field.Index.TOKENIZED));
        writer.addDocument(doc);
//        writer.optimize();// 优化
        writer.close();// 一定要关闭,否则不能把内存中的数据写到文件
        Date end = new Date();
        System.out.println("索引建立成功!!!!" + "用时" + (end.getTime() - start.getTime()) + "毫秒");
      } catch (IOException e) {
        System.out.println(e);
      }
    }
  }

  public Hits seacherWildcard(String queryString) {// 根据关键字搜索
    Hits hits = null;
    try {
      Query query = new WildcardQuery(new Term("subject", "*" + queryString + "*"));// 模糊查询一下
      Searcher searcher = new IndexSearcher(indexPath);
      hits = searcher.search(query);
      for (int i = 0; i < hits.length(); i++) {
        Document doc = hits.doc(i);
      }
      searcher.close();
    } catch (Exception e) {
      System.out.print(e);
    }
    return hits;
  }

  public List seacherIndex(String queryString) {// 根据关键字搜索
    System.out.println(queryString);
    Hits hits = null;
    try {
      IndexSearcher isearcher = new IndexSearcher(indexPath);
      // Parse a simple query that searches for "text":
      MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[]{"subject","content"},getAnalyzer());
//      QueryParser parser = new QueryParser("subject", getAnalyzer());
      Query query = parser.parse(queryString);
      hits = isearcher.search(query);
      List rtn = new ArrayList();
      for (int i = 0; i < hits.length(); i++) {
        Document doc = hits.doc(i);
        rtn.add(Long.parseLong(doc.get("id").trim()));
      }
      isearcher.close();
      return rtn;
    } catch (Exception e) {
      System.out.print(e);
      return null;
    }
  }
}

说明

1 StandardAnalyzer 支持中文,所以不用再找其它的了

2 Index方法里

IndexWriter writer = new IndexWriter(indexPath, getAnalyzer(), true); 

最后面的这个true,是重新建立索引。 在第一运行时,必须重新所有所有。

 Field.Index.UN_TOKENIZED 是不进行单词拆分   Field.Index.TOKENIZED 是进行拆分,

3 seacherWildcard 里面可以进行模糊搜索

4 seacherIndex 里面   MultiFieldQueryParser 支持多个字段的联合查询

5 我测试的结果,我的网站的11M的索引(应该算很一般的数据量,6000多个帖子),检索竟然几乎不需要时间?或者10毫秒以内。

6  l.seacherIndex("域名 AND 系统"); AND OR NOT 用在单词之间进行组合查询, + 代表 AND  -代表 NOT

7 每次有新的数据时,比如发言或者回复则调用

public void IndexSingle(long id, String subject, String content)

进行索引更新,注意里面的参数是false;

IndexWriter writer = new IndexWriter(indexPath, getAnalyzer(), false);
就这些,第一次使用,效果很好。





<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
本指南详细阐述基于Python编程语言结合OpenCV计算机视觉库构建实眼部状态分析系统的技术流程。该系统能够准确识别眼部区域,并对眨眼动作与持续闭眼状态进行判别。OpenCV作为功能强大的图像处理工具库,配合Python简洁的语法特性与丰富的第三方模块支持,为开发此类视觉应用提供了理想环境。 在环境配置阶段,除基础Python运行环境外,还需安装OpenCV核心模块与dlib机器学习库。dlib库内置的HOG(方向梯度直方图)特征检测算法在面部特征定位方面表现卓越。 技术实现包含以下关键环节: - 面部区域检测:采用预训练的Haar级联分类器或HOG特征检测器完成初始人脸定位,为后续眼部分析建立基础坐标系 - 眼部精确定位:基于已识别的人脸区域,运用dlib提供的面部特征点预测模型准确标定双眼位置坐标 - 眼睑轮廓分析:通过OpenCV的轮廓提取算法精确勾勒眼睑边缘形态,为状态判别提供几何特征依据 - 眨眼动作识别:通过连续帧序列分析眼睑开合度变化,建立动态阈值模型判断瞬闭合动作 - 持续闭眼检测:设定更严格的状态持续间与闭合程度双重标准,准确识别长间闭眼行为 - 实处理架构:构建视频流处理管线,通过帧捕获、特征分析、状态判断的循环流程实现实监控 完整的技术文档应包含模块化代码实现、依赖库安装指引、参数调优指南及常见问题解决方案。示例代码需具备完整的错误处理机制与性能优化建议,涵盖图像预处理、光照补偿等实际应用中的关键技术点。 掌握该技术体系不仅有助于深入理解计算机视觉原理,更为疲劳驾驶预警、医疗监护等实际应用场景提供了可靠的技术基础。后续优化方向可包括多模态特征融合、深度学习模型集成等进阶研究领域。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值