1、准备工作
下载lucene 3.6.1 : http://lucene.apache.org/
下载中文分词IK Analyzer: http://code.google.com/p/ik-analyzer/downloads/list (注意下载的是IK Analyzer 2012_u5_source.zip,其他版本有bug)
下载solr 3.6.1: http://lucene.apache.org/solr/(编译IK Analyzer时需引用包)
OK,将lucene 、solr 相关包(lucene-core-3.6.1.jar、lucene-highlighter-3.6.1.jar、lucene-analyzers-3.6.1.jar、apache-solr-core-3.6.1.jar、apache-solr-solrj-3.6.1.jar)拷贝到项目lib下,IK源码置于项目src下。
2、从Oracle数据库中取数据创建索引(使用IK分词)
package lucene.util; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.store.Directory; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.util.Version; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.wltea.analyzer.lucene.IKAnalyzer; import java.sql.Connection; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import modules.gk.Gk_info; import modules.gk.Gk_infoSub; import web.sys.Globals; import web.db.DBConnector; import web.db.ObjectCtl; import web.util.StringUtil; //Wizzer.cn public class LuceneIndex { IndexWriter writer = null; FSDirectory dir = null; boolean create = true; public void init() { long a1 = System.currentTimeMillis(); System.out.println("[Lucene 开始执行:" + new Date() + "]"); Connection con = DBConnector.getconecttion(); //取得一个数据库连接 try { final File docDir = new File(Globals.SYS_COM_CONFIG.get("sys.index.path").toString());//E:\lucene if (!docDir.exists()) { docDir.mkdirs(); } String cr = Globals.SYS_COM_CONFIG.get("sys.index.create").toString();//true or false if ("false".equals(cr.toLowerCase())) { create = false; } Directory dir = FSDirectory.open(docDir); // Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_36); Analyzer analyzer = new IKAnalyzer(true); IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_36, analyzer); if (create) { // Create a new index in the directory, removing any // previously indexed documents: iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE); } else { // Add new documents to an existing index: iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); } IndexWriter writer = new IndexWriter(dir, iwc); String sql = "SELECT indexno,title,describes,pdate,keywords FROM TABLEA WHERE STATE=1 AND SSTAG<>1 "; int rowCount = ObjectCtl.getRowCount(con, sql); int pageSize = StringUtil.StringToInt(Globals.SYS_COM_CONFIG.get("sys.index.size").toString()); //每页记录数 int pages = (rowCount - 1) / pageSize + 1; //计算总页数 ArrayList list = null; Gk_infoSub gk = null; for (int i = 1; i < pages+1; i++) { long a = System.currentTimeMillis(); list = ObjectCtl.listPage(con, sql, i, pageSize, new Gk_infoSub()); for (int j = 0; j < list.size(); j++) { gk = (Gk_infoSub) list.get(j); Document doc = new Document(); doc.add(new Field("indexno", StringUtil.null2String(gk.getIndexno()), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));//主键不分词 doc.add(new Field("title", StringUtil.null2String(gk.getTitle()), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("describes", StringUtil.null2String(gk.getDescribes()), Field.Store.YES, Field.Index.ANALYZED)); doc.add(new Field("pdate", StringUtil.null2String(gk.getPdate()), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));//日期不分词 doc.add(new Field("keywords", StringUtil.null2String(gk.getKeywords()), Field.Store.YES, Field.Index.ANALYZED)); writer.addDocument(doc); ObjectCtl.executeUpdateBySql(con,"UPDATE TABLEA SET SSTAG=1 WHERE indexno='"+gk.getIndexno()+"'");//更新已索引状态 } long b = System.currentTimeMillis(); long c = b - a; System.out.println("[Lucene " + rowCount + "条," + pages + "页,第" + i + "页花费时间:" + c + "毫秒]"); } writer.commit(); } catch (Exception e) { e.printStackTrace(); } finally { DBConnector.freecon(con); //释放数据库连接 try { if (writer != null) { writer.close(); } } catch (CorruptIndexException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (dir != null && IndexWriter.isLocked(dir)) { IndexWriter.unlock(dir);//注意解锁 } } catch (IOException e) { e.printStackTrace(); } } } long b1 = System.currentTimeMillis(); long c1 = b1 - a1; System.out.println("[Lucene 执行完毕,花费时间:" + c1 + "毫秒,完成时间:" + new Date() + "]"); } }
3、单字段查询以及多字段分页查询高亮显示
package lucene.util; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.store.Directory; import org.apache.lucene.search.*; import org.apache.lucene.search.highlight.SimpleHTMLFormatter; import org.apache.lucene.search.highlight.Highlighter; import org.apache.lucene.search.highlight.SimpleFragmenter; import org.apache.lucene.search.highlight.QueryScorer; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.queryParser.MultiFieldQueryParser; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.KeywordAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.util.Version; import modules.gk.Gk_infoSub; import java.util.ArrayList; import java.io.File; import java.io.StringReader; import java.lang.reflect.Constructor; import web.util.StringUtil; import web.sys.Globals; import org.wltea.analyzer.lucene.IKAnalyzer; //Wizzer.cn public class LuceneQuery { private static String indexPath;// 索引生成的目录 private int rowCount;// 记录数 private int pages;// 总页数 private int currentPage;// 当前页数 private int pageSize; //每页记录数 public LuceneQuery() { this.indexPath = Globals.SYS_COM_CONFIG.get("sys.index.path").toString(); } public int getRowCount() { return rowCount; } public int getPages() { return pages; } public int getPageSize() { return pageSize; } public int getCurrentPage() { return currentPage; } /** * 函数功能:根据字段查询索引 */ public ArrayList queryIndexTitle(String keyWord, int curpage, int pageSize) { ArrayList list = new ArrayList(); try { if (curpage <= 0) { curpage = 1; } if (pageSize <= 0) { pageSize = 20; } this.pageSize = pageSize; //每页记录数 this.currentPage = curpage; //当前页 int start = (curpage - 1) * pageSize; Directory dir = FSDirectory.open(new File(indexPath)); IndexReader reader = IndexReader.open(dir); IndexSearcher searcher = new IndexSearcher(reader); Analyzer analyzer = new IKAnalyzer(true); QueryParser queryParser = new QueryParser(Version.LUCENE_36, "title", analyzer); queryParser.setDefaultOperator(QueryParser.AND_OPERATOR); Query query = queryParser.parse(keyWord); int hm = start + pageSize; TopScoreDocCollector res = TopScoreDocCollector.create(hm, false); searcher.search(query, res); SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>"); Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query)); this.rowCount = res.getTotalHits(); this.pages = (rowCount - 1) / pageSize + 1; //计算总页数 TopDocs tds = res.topDocs(start, pageSize); ScoreDoc[] sd = tds.scoreDocs; for (int i = 0; i < sd.length; i++) { Document hitDoc = reader.document(sd[i].doc); list.add(createObj(hitDoc, analyzer, highlighter)); } } catch (Exception e) { e.printStackTrace(); } return list; } /** * 函数功能:根据字段查询索引 */ public ArrayList queryIndexFields(String allkeyword, String onekeyword, String nokeyword, int curpage, int pageSize) { ArrayList list = new ArrayList(); try { if (curpage <= 0) { curpage = 1; } if (pageSize <= 0) { pageSize = 20; } this.pageSize = pageSize; //每页记录数 this.currentPage = curpage; //当前页 int start = (curpage - 1) * pageSize; Directory dir = FSDirectory.open(new File(indexPath)); IndexReader reader = IndexReader.open(dir); IndexSearcher searcher = new IndexSearcher(reader); BooleanQuery bQuery = new BooleanQuery(); //组合查询 if (!"".equals(allkeyword)) {//包含全部关键词 KeywordAnalyzer analyzer = new KeywordAnalyzer(); BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD};//AND Query query = MultiFieldQueryParser.parse(Version.LUCENE_36, allkeyword, new String[]{"title", "describes", "keywords"}, flags, analyzer); bQuery.add(query, BooleanClause.Occur.MUST); //AND } if (!"".equals(onekeyword)) { //包含任意关键词 Analyzer analyzer = new IKAnalyzer(true); BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD};//OR Query query = MultiFieldQueryParser.parse(Version.LUCENE_36, onekeyword, new String[]{"title", "describes", "keywords"}, flags, analyzer); bQuery.add(query, BooleanClause.Occur.MUST); //AND } if (!"".equals(nokeyword)) { //排除关键词 Analyzer analyzer = new IKAnalyzer(true); BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD};//NOT Query query = MultiFieldQueryParser.parse(Version.LUCENE_36, nokeyword, new String[]{"title", "describes", "keywords"}, flags, analyzer); bQuery.add(query, BooleanClause.Occur.MUST_NOT); //AND } int hm = start + pageSize; TopScoreDocCollector res = TopScoreDocCollector.create(hm, false); searcher.search(bQuery, res); SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style='color:red'>", "</span>"); Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(bQuery)); this.rowCount = res.getTotalHits(); this.pages = (rowCount - 1) / pageSize + 1; //计算总页数 System.out.println("rowCount:" + rowCount); TopDocs tds = res.topDocs(start, pageSize); ScoreDoc[] sd = tds.scoreDocs; Analyzer analyzer = new IKAnalyzer(); for (int i = 0; i < sd.length; i++) { Document hitDoc = reader.document(sd[i].doc); list.add(createObj(hitDoc, analyzer, highlighter)); } } catch (Exception e) { e.printStackTrace(); } return list; } /** * 创建返回对象(高亮) */ private synchronized static Object createObj(Document doc, Analyzer analyzer, Highlighter highlighter) { Gk_infoSub gk = new Gk_infoSub(); try { if (doc != null) { gk.setIndexno(StringUtil.null2String(doc.get("indexno"))); gk.setPdate(StringUtil.null2String(doc.get("pdate"))); String title = StringUtil.null2String(doc.get("title")); gk.setTitle(title); if (!"".equals(title)) { highlighter.setTextFragmenter(new SimpleFragmenter(title.length())); TokenStream tk = analyzer.tokenStream("title", new StringReader(title)); String htext = StringUtil.null2String(highlighter.getBestFragment(tk, title)); if (!"".equals(htext)) { gk.setTitle(htext); } } String keywords = StringUtil.null2String(doc.get("keywords")); gk.setKeywords(keywords); if (!"".equals(keywords)) { highlighter.setTextFragmenter(new SimpleFragmenter(keywords.length())); TokenStream tk = analyzer.tokenStream("keywords", new StringReader(keywords)); String htext = StringUtil.null2String(highlighter.getBestFragment(tk, keywords)); if (!"".equals(htext)) { gk.setKeywords(htext); } } String describes = StringUtil.null2String(doc.get("describes")); gk.setDescribes(describes); if (!"".equals(describes)) { highlighter.setTextFragmenter(new SimpleFragmenter(describes.length())); TokenStream tk = analyzer.tokenStream("keywords", new StringReader(describes)); String htext = StringUtil.null2String(highlighter.getBestFragment(tk, describes)); if (!"".equals(htext)) { gk.setDescribes(htext); } } } return gk; } catch (Exception e) { e.printStackTrace(); return null; } finally { gk = null; } } private synchronized static Object createObj(Document doc) { Gk_infoSub gk = new Gk_infoSub(); try { if (doc != null) { gk.setIndexno(StringUtil.null2String(doc.get("indexno"))); gk.setPdate(StringUtil.null2String(doc.get("pdate"))); gk.setTitle(StringUtil.null2String(doc.get("title"))); gk.setKeywords(StringUtil.null2String(doc.get("keywords"))); gk.setDescribes(StringUtil.null2String(doc.get("describes"))); } return gk; } catch (Exception e) { e.printStackTrace(); return null; } finally { gk = null; } } }
单字段查询:
long a = System.currentTimeMillis(); try { int curpage = StringUtil.StringToInt(StringUtil.null2String(form.get("curpage"))); int pagesize = StringUtil.StringToInt(StringUtil.null2String(form.get("pagesize"))); String title = StringUtil.replaceLuceneStr(StringUtil.null2String(form.get("title"))); LuceneQuery lu = new LuceneQuery(); form.addResult("list", lu.queryIndexTitle(title, curpage, pagesize)); form.addResult("curPage", lu.getCurrentPage()); form.addResult("pageSize", lu.getPageSize()); form.addResult("rowCount", lu.getRowCount()); form.addResult("pageCount", lu.getPages()); } catch (Exception e) { e.printStackTrace(); } long b = System.currentTimeMillis(); long c = b - a; System.out.println("[搜索信息花费时间:" + c + "毫秒]");
多字段查询:
long a = System.currentTimeMillis(); try { int curpage = StringUtil.StringToInt(StringUtil.null2String(form.get("curpage"))); int pagesize = StringUtil.StringToInt(StringUtil.null2String(form.get("pagesize"))); String allkeyword = StringUtil.replaceLuceneStr(StringUtil.null2String(form.get("allkeyword"))); String onekeyword = StringUtil.replaceLuceneStr(StringUtil.null2String(form.get("onekeyword"))); String nokeyword = StringUtil.replaceLuceneStr(StringUtil.null2String(form.get("nokeyword"))); LuceneQuery lu = new LuceneQuery(); form.addResult("list", lu.queryIndexFields(allkeyword,onekeyword,nokeyword, curpage, pagesize)); form.addResult("curPage", lu.getCurrentPage()); form.addResult("pageSize", lu.getPageSize()); form.addResult("rowCount", lu.getRowCount()); form.addResult("pageCount", lu.getPages()); } catch (Exception e) { e.printStackTrace(); } long b = System.currentTimeMillis(); long c = b - a; System.out.println("[高级检索花费时间:" + c + "毫秒]");
4、Lucene通配符查询
BooleanQuery bQuery = new BooleanQuery(); //组合查询 if (!"".equals(title)) { WildcardQuery w1 = new WildcardQuery(new Term("title", title+ "*")); bQuery.add(w1, BooleanClause.Occur.MUST); //AND } int hm = start + pageSize; TopScoreDocCollector res = TopScoreDocCollector.create(hm, false); searcher.search(bQuery, res);
5、Lucene嵌套查询
实现SQL:(unitid like 'unitid%' and idml like 'id2%') or (tounitid like 'unitid%' and tomlid like 'id2%' and tostate=1)
BooleanQuery bQuery = new BooleanQuery(); BooleanQuery b1 = new BooleanQuery(); WildcardQuery w1 = new WildcardQuery(new Term("unitid", unitid + "*")); WildcardQuery w2 = new WildcardQuery(new Term("idml", id2 + "*")); b1.add(w1, BooleanClause.Occur.MUST);//AND b1.add(w2, BooleanClause.Occur.MUST);//AND bQuery.add(b1, BooleanClause.Occur.SHOULD);//OR BooleanQuery b2 = new BooleanQuery(); WildcardQuery w3 = new WildcardQuery(new Term("tounitid", unitid + "*")); WildcardQuery w4 = new WildcardQuery(new Term("tomlid", id2 + "*")); WildcardQuery w5 = new WildcardQuery(new Term("tostate", "1")); b2.add(w3, BooleanClause.Occur.MUST);//AND b2.add(w4, BooleanClause.Occur.MUST);//AND b2.add(w5, BooleanClause.Occur.MUST);//AND bQuery.add(b2, BooleanClause.Occur.SHOULD);//OR
6、Lucene先根据时间排序后分页
int hm = start + pageSize; Sort sort = new Sort(new SortField("pdate", SortField.STRING, true)); TopScoreDocCollector res = TopScoreDocCollector.create(pageSize, false); searcher.search(bQuery, res); this.rowCount = res.getTotalHits(); this.pages = (rowCount - 1) / pageSize + 1; //计算总页数 TopDocs tds =searcher.search(bQuery,rowCount,sort);// res.topDocs(start, pageSize); ScoreDoc[] sd = tds.scoreDocs; System.out.println("rowCount:" + rowCount); int i=0; for (ScoreDoc scoreDoc : sd) { i++; if(i<start){ continue; } if(i>hm){ break; } Document doc = searcher.doc(scoreDoc.doc); list.add(createObj(doc));
这个效率不高,正常的做法是创建索引的时候进行排序,之后使用分页方法,不要这样进行2次查询。
推荐阅读:基于Lucene4.6+Solr4.6+Heritrix1.14+S2SH实战开发从无到有垂直搜索引擎
Lucene视频教程下载: http://pan.baidu.com/s/1mgwWDxY 密码: y271
咨询qq:1840215592
相关推荐
本文将深入探讨如何在Lucene中实现高亮显示搜索结果和高效的分页功能,帮助开发者更好地理解和运用这个强大的工具。 一、Lucene简介 Lucene的核心功能是提供文本的索引和搜索,其内部实现了高效的倒排索引结构,...
5. **结果高亮**:为了提高用户体验,搜索结果中匹配的关键词会被高亮显示,让用户一目了然地看到关键词在内容中的位置。 在实际应用中,后端系统会接收前端用户的查询请求,使用Lucene进行搜索,并将结果返回给...
总的来说,"Lucene5.3.1相关jar包"包含了构建高效全文搜索引擎所需的组件,特别是对于中文文本的处理,它提供了中文分词器和结果高亮功能,使得开发者能够轻松地在Java项目中集成先进的信息检索能力。在使用这些jar...
Lucene的核心组件包括索引、查询解析、排序和结果集的高亮显示等。 源代码中可能涵盖以下几个主要方面: 1. **索引构建**:展示了如何使用Lucene来读取和索引文本数据,包括从文件系统、数据库或其他数据源中抽取...
**Lucene 概述** Lucene 是一个高性能、全文本搜索库...实际的 "luceneDemo" 可能包含更丰富的功能,例如支持多字段查询、高亮显示搜索结果、分页显示等。学习和理解 Lucene,可以帮助开发者构建强大的全文检索系统。
此外,客户端还需要处理分页、排序和高亮显示等需求。 Paoding作为中文分词工具,它的主要任务是对用户输入的中文文本进行切分,将其转化为一系列的词汇单元。由于中文没有明显的空格分隔,分词对于中文搜索至关...
4. **高亮显示(Highlighting)**:为了提高用户体验,可以使用Highlighter组件高亮显示查询词在搜索结果中的位置。 **三、Lucene的高级特性** 1. **多字段搜索**:Lucene支持对多个字段进行同时搜索,通过...
在本实例中,我们将深入探讨Lucene 4.7版本,涵盖索引的创建、修改、删除,以及查询时的排序、分页、优化和高亮显示等功能。此外,我们还将了解如何使用不同的分词器,以适应不同场景的需求。 首先,让我们从基础...
同时,可以提供分页、高亮显示匹配关键词等功能,提升用户体验。 在“lucene_web”项目中,我们还能看到如何利用Lucene的Filter和Collector来实现特定的搜索需求,例如范围查询、模糊查询、短语查询等。同时,通过...
- 分页和高亮显示:限制每次返回的结果数量,使用 `Highlighter` 高亮匹配的关键词。 综上所述,Lucene 示例项目提供了完整的站内搜索解决方案,涉及数据预处理、索引构建、查询执行、结果处理等多个环节。通过学习...
2. 高亮显示:Lucene支持搜索结果中的关键词高亮,帮助用户快速定位匹配部分。 3. 近实时搜索:通过NRTManager(Near Real Time)机制,Lucene能在短时间内更新索引并反映到搜索结果中。 总结,Lucene提供了丰富的...
对于高亮显示结果时丢失标点的问题,可以通过选择合适的分析器,如IK分词器,来解决。最后,搜索结果的显示数量可以通过TopScoreDocCollector来控制,定义要返回的文档数,并通过score方法收集相关文档。 总之,...
封装搜索服务是为了提供统一的搜索接口,可以包括分页搜索、高亮显示、排序等功能。一个典型的SearchService类会接收查询参数,执行搜索操作,返回搜索结果集。 #### 2.4 结果集处理 封装结果集处理能帮助我们更好...
- **高级特性探索**:深入探讨 Lucene 的一些高级特性,如高亮显示、近似匹配等。 #### 知识点四:Lucene 内部原理与定制化 除了基本的使用指南之外,《Lucene in Action》还深入剖析了 Lucene 的内部工作原理,为...
Lucene 3.6.1: 中文分词、创建索引库、排序、多字段分页查询以及高亮显示源 希望对大家有帮助, 我自己建立的mysql数据库 使用了IKAnalyzer分词器源代码,大家可以自己设置停词,也可以自己改写算法
在这个“lucene5.5demo”项目中,开发者利用Lucene 5.5版本,结合Spring MVC框架和MySQL数据库,构建了一个功能完备的文本搜索系统,涵盖了索引的创建、更新、删除和查询等基本操作,并实现了高亮显示、分页以及...
3. **排序与高亮**:可以根据相关度或其他字段值对结果排序,同时可以高亮显示匹配的部分。 4. **分页检索**:支持分页显示搜索结果,提高用户体验。 5. **分布式搜索**:通过Solr或Elasticsearch扩展,支持大规模...
2.2.0版本中,Lucene提供了高亮查询结果的功能,可以突出显示搜索关键词在文档中的位置,提升用户体验。 三、工作流程 3.1 文档分析与索引 首先,使用Analyzer对文档内容进行分析,然后通过IndexWriter创建索引。...
5. **结果处理**:如何获取和展示搜索结果,可能包括排序、过滤和高亮显示相关匹配内容。 6. **Java编程实践**:展示了如何在Java项目中导入和使用Lucene库,以及面向对象的设计模式在搜索引擎开发中的应用。 对于...
5. **高亮显示**:可以将搜索关键词在结果文档中高亮显示,提高用户体验。 二、主要功能 1. **索引构建**:从各种数据源(如文件、数据库等)读取内容,创建索引结构。 2. **索引更新**:支持增量索引,仅对变动...