• 1. Lucene&Solr苏宁易购搜索组
  • 2. 搜索引擎结构文档文本提取索引程序索引库(Lucene)搜索查询服务器(Solr)文件数据库爬虫NBA搜索
  • 3. Lucene是什么包括 全文索引库 简单的语言解析功能 不包括 爬虫 文档格式解析 “PageRank”等排序算法
  • 4. Lucene来源与发展1999 Cutting 开发的第一个Java程序 2001 捐赠给Apache 2004年11月 1.4.3版本 2008年10月 2.4.0版本 2009年11月 3.0.0版本
  • 5. Lucene的用户国际 Twitter IBM LinkedIn 捐出分类统计的子项目bobo-browse和 实时搜索的项目Zoie 国内 凤凰网 敦煌网 豆丁
  • 6. 全文索引结构12435词:文档:北京武汉天津上海大连
  • 7. Lucene中的倒排索引
  • 8. 索引相关类DocumentAnalyzerIndexWriterField(Title)通过IndexWriter来写索引,通过IndexReader读索引。 一段有意义的文字需要通过Analyzer分割成一个个词语后才能按关键词搜索。Analyzer就是分析器,StandardAnalyzer是Lucene中最常用的分析器。  TokenStream实例保存着当前的Attribute状态。 Attribute 是一个接口,实现中包含一个代表词本身含义的字符串和该词在文章中相应的起止偏移位置, Attribute还可以用来存储词类型或语义信息。  一个Document代表索引库中的一条记录。要搜索的信息封装成Document后通过IndexWriter写入索引库。调用Searcher接口按关键词搜索后,返回的也是一个封装后的Document的列表。  一个Document可以包含多个列,叫做field。例如一篇文章可以包含“标题”、“正文”、“修改时间”等field,创建这些列对象以后,可以通过Document的add方法增加这些列。Field(Body)Field(URL)
  • 9. AnalyzerAnalyzer analyzer = new StandardAnalyzer(); // or any other analyzer TokenStream ts = analyzer.tokenStream("myfield",new StringReader("some text goes here")); while (ts.incrementToken()) { System.out.println("token: "+ts)); }
  • 10. 创建索引//创建新的索引或者对已有的索引增加文档 index = new IndexWriter(indexDirectory, new StandardAnalyzer(Version.LUCENE_CURRENT), !incremental, IndexWriter.MaxFieldLength.UNLIMITED); File dir = new File(sSourceDir); indexDir(dir); //索引路径 index.optimize();//索引优化 index.close();//关闭索引库
  • 11. 向索引增加文档Document doc = new Document(); //创建网址列 Field f = new Field("url", news.URL , Field.Store.YES, Field.Index. NOT_ANALYZED,//不分词 Field.TermVector.NO); doc.add(f); //创建标题列 f = new Field("title", news.title , Field.Store.YES, Field.Index.ANALYZED,//分词 Field.TermVector.WITH_POSITIONS_OFFSETS);//存Token位置信息 doc.add(f); //创建内容列 f = new Field("body", news.body , Field.Store.YES, Field.Index. ANALYZED, //分词 Field.TermVector.WITH_POSITIONS_OFFSETS); //存Token位置信息 doc.add(f); index.addDocument(doc);
  • 12. 搜索// read-only=true IndexSearcher isearcher = new IndexSearcher(directory, true); // Parse a simple query that searches for "text": QueryParser parser = new QueryParser(Version.LUCENE_CURRENT,"fieldname", analyzer); Query query = parser.parse("text"); //返回前1000条搜索结果 ScoreDoc[] hits = isearcher.search(query, 1000).scoreDocs; //遍历结果 for (int i = 0; i < hits.length; i++) { Document hitDoc = isearcher.doc(hits[i].doc); System.out.println(hitDoc.get("fieldname")); } isearcher.close(); directory.close();
  • 13. 常用查询Query说明用法TermQuery最基本的词条查询查询不切分的字段或者基本词BooleanQuery布尔逻辑查询组合条件查询PhraseQuery短语匹配查询要求精确匹配的查询SpanQuery匹配位置相关的查询 (跨度查询)字词混合查询FieldScoreQuery函数查询(通过数字型的字段影响排序结果)时间加权排序
  • 14. 2.9以前版本区间查询的问题 RangeQuery采用扩展成TermQuery来实现,如果查询区间范围太大,RangeQuery会导致TooManyClausesException ConstantScoreRangeQuery 内部采用Filter来实现,当索引很大的时候,查询速度会很慢
  • 15. Trie结构区间查询 例如:TrieRange:[423 TO 642]分解为5个子条件来执行: handreds:5 OR tens:[43 TO 49] OR ones:[423 TO 429] OR tens:[60 TO 63] OR ones:[640 TO 642]
  • 16. 查询语法加权 solr^4 lucene 修饰符 + - NOT +solr lucene 布尔操作符 OR AND (solr OR lucene) AND user 按域查询 title:NBA
  • 17. QueryParserQueryParser将输入查询字串解析为Lucene Query对象。 QueryParser是使用JavaCC(Java Compiler Compiler )工具生成的词法解析器。 QueryParser.jj中定义了查询语法。 需要让QueryParser更好的支持中文,例如全角空格等?
  • 18. Filter 可以定义Filter类来过滤查询结果。也可以缓存和重用Filter。如下条件可用Filter来实现: 根据不同的安全权限显示搜索结果; 仅查看上个月的数据; 在某个类别中查找。
  • 19. BestDriversFilter BestDriversFilter 把结果限定到score 是5 的司机。 public class BestDriversFilter extends Filter{ @Override public DocIdSet getDocIdSet(IndexReader reader) throws IOException { OpenBitSet bitSet = new OpenBitSet( reader.maxDoc() ); TermDocs termDocs = reader.termDocs( new Term( "score", "5" ) ); while ( termDocs.next() ) { bitSet.set( termDocs.doc() ); } return bitSet; } }
  • 20. 使用Filter Filter bestDriversFilter = new BestDriversFilter(); //query不变, 增加bestDriversFilter ScoreDoc[] hits = isearcher.search(query, bestDriversFilter, 1000).scoreDocs; //返回的结果可能比以前少了
  • 21. 分类统计(Faceted Search)
  • 22. Filter实现的分类统计 String[] cats = {"001004003","001008003021","001004014" }; //类别数组 long[] catCounts = new long[cats.length];//分类统计结果 //原始查询 Filter all = new QueryWrapperFilter(q); //用AND逻辑合并Filter ChainedFilter.DEFAULT = ChainedFilter.AND; for (int i=0;i
  • 23. Solr起源Lucene仅仅是一个全文检索包,不是一个独立的搜索服务 Solr来源于CNET.com的内部数据库检索项目 Solr的含义是:"Searching On Lucene w/Replication "   Solr当前主要主要代码维护者Yonik斯坦福大学硕士毕业
  • 24. Solr发展过程2004秋天,CNET启动Solr项目的前生Solar 2005夏天,CNET产品目录搜索开始使用Solar 2006年1月捐赠给Apache 2007年1月Solr毕业成为Lucene的子项目并发布1.2版本 2008年9月发布 1.3.0版本 2009年11月发布1.4版本
  • 25. Solr用户国际 AOL CNET Disney Apple, Inc. 国内 阿里巴巴 安居客 新聚思(SYNNEX)
  • 26. Solr搜索服务器的特点是Web Server中的Servlet 积极的缓存(自动加载搜索热词等) Web管理界面 XML/HTTP, JSON 接口 Faceting(分类统计搜索结果) 通过Schema配置文件定义types 和 fields 为了并发访问,实现主从式的索引复制
  • 27. 使用Solr搜索服务器Java客户端-SolrJ 通过Java 二进制格式快速返回结果
  • 28. Schema.xml
  • 29. Schema.xml指定id为唯一列 id 指定body为默认搜索列。 body
  • 30. solrconfig.xml用来配置solr运行的系统参数,例如缓存,插件等。 预热搜索数量最好少于CPU核数量 4
  • 31. 增加数据HTTP POST to http://localhost:8983/solr/update/ 05991 Bridgewater Perl Java [ ... [ ... ]]
  • 32. 更新/删除数据更新 若增加文档的主键已经存在索引库中,则替换已有的。 删除 通过主键删除 05991 通过查询删除 name:Anthony
  • 33. Solr的后台管理界面
  • 34. Solr后台查询实例查询(Query),根据查询条件可以得到查询结果,例如*:*查询条件查询结果数查询用时
  • 35. Search基本参数 qt – 查询类型 (request handler),例如 standard wt – 返回格式类型(response writer),例如xml或json 公共参数 q – 查询词 sort – 排序方式 start - 返回结果的开始行 rows -本次需要返回结果的行数 fl – 需要返回的列名称
  • 36. Faceted Searchhttp://localhost:8983/solr/select?q=ipod&rows=0&facet=true&facet.limit=-1&facet.field=cat&facet.mincount=1&facet.field=inStock 0 3 1 2 3 3 1
  • 37. 搜索界面
  • 38. 检索案例http://www.alljournals.cn/ (前端.net)http://www.xiaoxishu.com/ (前端PHP)
  • 39. 商业支持Lucene http://www.searchblox.com Solr http://www.lucidimagination.com http://www.lietu.com
  • 40. 谢谢! http://www.lietu.com