• 1. Lucene培训 搜索组 2011年7月
  • 2. 议题全文搜索的基本原理Lucene简介Lucene工程代码结构核心Index类介绍Lucene各种Query
  • 3. 3全文搜索流程
  • 4. 4全文检索概念 索引创建 将现实世界中的非结构化与结构化的数据提取信息,创建索引的过程 搜索索引 得到用户的查询请求,搜索创建的索引,然后返回结果的过程
  • 5. 例子 假如我们的文档集中有100篇文档,为了方便表示,我们为文档编码从1到100.得到以下的结构。 字典:左边的字符串 倒排表:每个字符串指向包含此字符串的文档(Document)的链表 索引=字典+倒排表 5索引的数据结构
  • 6. 议题全文搜索的基本原理Lucene简介Lucene工程代码结构核心Index类介绍Lucene各种Query
  • 7. Lucene简介包括 全文检索类库 简单的语言解析功能 不包括 爬虫 文档格式解析 7
  • 8. Lucene的特性纯Java代码,跨平台,使用简单 速度快 API使用简单 提供并发索引,搜索 增量索引 Boolean + Vector Space ,排序等 8
  • 9. 9议题全文搜索的基本原理Lucene简介Lucene工程代码结构核心Index类介绍Lucene各种Query
  • 10. Lucene工程代码结构Lucene源代码结构10
  • 11. analysis对需要建立索引的文本进行分词、过滤等操作 standard是标准分析器 document提供对Document和Field的各种操作的支持。 index是最重要的包,用于向Lucene提供建立索引时各种操作的支持 queryParser提供检索时的分析支持 search负责检索 store提供对索引存储的支持 util提供一些常用工具类和常量类的支持 11
  • 12. 12议题全文搜索的基本原理Lucene简介Lucene工程代码结构核心Index类介绍Lucene各种Query
  • 13. 核心Index类IndexWriter Directory Analyzer Document Field13
  • 14. IndexWriterAnalyzer analyzer = new PaodingAnalyzer(); //读取本类目录下的text.txt文件 String content = ContentReader.readText(Chinese.class); Directory ramDir = new RAMDirectory(); IndexWriter writer = new IndexWriter(ramDir, analyzer, MaxFieldLength.UNLIMITED); Document doc = new Document(); Field fd = new Field(FIELD_NAME, content, Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); doc.add(fd); writer.addDocument(doc); writer.optimize(); writer.close();14Paoding分词器   RAMDirectory在内存中存放索引,读取速度快,但程序一运行结束,它的内容就不存在了
  • 15. IndexWriter说明创建新的索引 将文档(Document)添加到索引中 IndexWriter writer = new IndexWriter(ramDir, analyzer, true,MaxFieldLength.UNLIMITED); 第三个参数:为true时,IndexWriter不管目录内是否已经有索引了,一律清空,重新建立;当为false时,则IndexWriter会在原有基础上增量添加索引。所以在更新的过程中,需要设置该值为false。 15
  • 16. Directory代表Lucene索引文件存放的路径 抽象类 允许子类存储索引 FSDirectory IndexWriter writer = new IndexWriter(FSDirectory.getDirectory(path, true), new StandardAnalyzer(), true);//删除原有索引 RAMDirectory IndexWriter writer = new IndexWriter(new RAMDirectory(), new StandardAnalyzer(), true); 16
  • 17. Analyzer在创建索引之前,文本先要通过分词处理 分词的作用就是把一串字符按照某种规则划分成一个个词语,并去除其中无效的词语。 以paoding中文分词为例子: 17
  • 18. DocumentDocument doc = new Document(); Field fd = new Field(FIELD_NAME, content, Field.Store.YES,Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);18
  • 19. Fieldnew Field(FIELD_NAME, content, Field.Store.YES,Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); (1)store类有3个公有的静态属性: Store.NO:表示该Field不需要存储 Store.YES:表示该Field需要存储 Store.COMPRESS:表示用压缩方式来保存这个Field的值 (2) index类有4个公有的静态属性 Field.Index.NO:不需要索引 Field.Index. ANALYZED:先被分词再被索引 Field.Index.NOT_ANALYZED:不对该Field进行分词,但会对它进行索引 Field.Index. NOT_ANALYZED_NO_NORMS:对该Field进行索引,但是不使用Analyzer, 同时禁止它参加评分,主要是为了减少内存的消耗。 Field.Index. ANALYZED_NO_NORMS:对该Field进行索引,但是使用Analyzer,同时禁止它参加评分,主要是为了减少内存的消耗。 19
  • 20. 2020议题全文搜索的基本原理Lucene简介Lucene工程代码结构核心Index类介绍Lucene各种Query
  • 21. 按词条搜索--TermQueryString content = "中国人民解放军"; Query query = null; query = new TermQuery(new Term("content", "人民")); Searcher searcher = new IndexSearcher(ramDir); IndexReader reader = IndexReader.open(ramDir); query = query.rewrite(reader); TopDocs hits = searcher.search(query, 10); for (int i = 0; i < hits.scoreDocs.length; i++) { int docId = hits.scoreDocs[i].doc; Document hit = searcher.doc(docId); String text = hit.get("content"); System.out.println(text); }21
  • 22. 按“与或”搜索--BooleanQueryString content = "中国人民解放军"; String title="人民文摘" ; Query query1 = new TermQuery(new Term("content", "解放军")); Query query2 = new TermQuery(new Term("title", "文摘")); BooleanQuery query = new BooleanQuery(); query.add(query1, BooleanClause.Occur.SHOULD); query.add(query2, BooleanClause.Occur.SHOULD); Searcher searcher = new IndexSearcher(ramDir); TopDocs hits = searcher.search(query, 10); 22
  • 23. QueryParser类1:默认为“或”关系: IndexReader reader = IndexReader.open(ramDir); String queryString = "中国人民解放军"; QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, "content", analyzer); //parser.setDefaultOperator(QueryParser.AND_OPERATOR); Query query = parser.parse(queryString); Searcher searcher = new IndexSearcher(ramDir); query = query.rewrite(reader); TopDocs hits = searcher.search(query, 10); 2:改变默认布尔逻辑 parser.setDefaultOperator(QueryParser.AND_OPERATOR);23分词之间是与关系
  • 24. 3:设置通配符,支持WildcardQuery * 表示0到多个字符 ? 表示一个单一的字符 IndexReader reader = IndexReader.open(ramDir); String queryString = "中国*"; QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, "content", analyzer); parser.setDefaultOperator(QueryParser.AND_OPERATOR); Query query = parser.parse(queryString); Searcher searcher = new IndexSearcher(ramDir); query = query.rewrite(reader); TopDocs hits = searcher.search(query, 10); 备注: http://lucene.apache.org/java/2_4_0/queryparsersyntax.html 查询语法 24
  • 25. 谢谢!