Lucene搜索引擎
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
字词混合查询
时间加权排序
区间查询
查询语法: time:[2007-08-13T00:00:00Z TO 200808-13T00:00:00Z] 调用代码: ConstantScoreRangeQuery dateQuery = new ConstantScoreRangeQuery("time", t1, t2, true, true);
搜索引擎解密
猎兔搜索 罗刚
搜索引擎结构
文件 文档
文本提取
索引程序
数据库
索引库(Lucene) 爬虫
搜索查询服务器(Solr)
NBA
搜索
Lucene是什么
• 包括
– 全文索引库 – 简单的语言解析功能
• 不包括
– 爬虫 – 文档格式解析 – “PageRank”等排序算法
Lucene来源与发展
• • • • • 1999 Cutting 开发的第一个Java程序 2001 捐赠给Apache 2004年11月 1.4.3版本 2008年10月 2.4.0版本 2009年11月 3.0.0版本
Trie结构实现的区间查询
在Lucene2.9以后的版本中,用Trie结构索引日期和数字等类型。例如:把521 这 个整数索引成为:百位是5、十位是52、个位是521。这样重复索引的好处是可 以用最低的精度搜索匹配区域的中心地带,用较高的精度匹配边界。这样减少了 要搜索的Term数量。
4
5
6
42
44
52
63
64
421
423
445
446
448
521
522
632
633
641
642
644
Range
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]
//用AND逻辑合并Filter ChainedFilter.DEFAULT = ChainedFilter.AND; for (int i=0;i<cats.length;++i) { //分类统计查询条件 Filter these = new QueryWrapperFilter(new TermQuery(new Term("cat", cats[i]))); ChainedFilter chainedFilter = new ChainedFilter( new Filter[]{all,these} ); //取得Filter中的BitSet的1 的个数 catCounts[i] = chainedFilter.getCardinality(reader); } return catCounts;
2.9以前版本区间查询的问题
• RangeQuery采用扩展成TermQuery 来实现,如果查询区间范围太大, RangeQuery会导致 TooManyClausesException • ConstantScoreRangeQuery 内部采用 Filter来实现,当索引很大的时候, 查询速度会很慢
Filter
可以定义Filter类来过滤查询结果。也 可以缓存和重用Filter。如下条件可用 Filter来实现: • 根据不同的安全权限显示搜索结果; • 仅查看上个月的数据; • 在某个类别中查找。
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; } }
创建索引
//创建新的索引或者对已有的索引增加文档 index = new IndexWriter(indexDirectory, new StandardAnalyzer(Version.LUCENE_CURRENT), !incremental, IndexWriter.MaxFieldLength.UNLIMITED); File dir = new File(sSourceDir); indexDir(dir); //索引路径
Analyzer
Analyzer 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)); }
Solr vs Sphinx
• Sphinx速度很快,但是不支持索引 复制和分发。有单点失败的问题 • Sphinx不支持搜索结果的高亮显示 • Sphinx没有对搜索结果的缓存 个人结论: Sphinx功能简单,速度 快,Solr速度慢点,但功能更全。
Solr起源
• Lucene仅仅是一个全文检索包,不 是一个独立的搜索服务 • Solr来源于CNET.com的内部数据库 检索项目 • Solr的含义是:"Searching On Lucene w/Replication " • Solr当前主要主要代码维护者Yonik 斯坦福大学硕士毕业
常用查询
Query TermQuery BooleanQuery PhraseQuery 说明 最基本的词条查询 布尔逻辑查询 短语匹配查询 用法 查询不切分的字段或 者基本词 组合条件查询 要求精确匹配的查询
SpanQuery
FieldScoreQuery
匹配位置相关的查询 (跨度查询)
函数查询(通过数字型 的字段影响排序结果)
搜索
// 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();
查询语法
• 加权 solr^4 lucene • 修饰符 + - NOT +solr lucene • 布尔操作符 OR AND (solr OR lucene) AND user • 按域查询 title:NBA
QueryParser
• QueryParser将输入查询字串解析为 Lucene Query对象。 • QueryParser是使用JavaCC(Java Compiler Compiler )工具生成的词法解析器。 • QueryParser.jj中定义了查询语法。 • 需要让QueryParser更好的支持中文, 例如全角空格等?
使用Filter
Filter bestDriversFilter = new BestDriversFilter(); //query不变, 增加bestDriversFilter ScoreDoc[] hits = isearcher.search(query, bestDriversFilter, 1000).scoreDocs; //返回的结果可能比以前少了
Lucene的用户
• 国际
Twitter IBM LinkedIn
捐出分类统计的子项目bobo-browse和 实时搜索的项目Zoie
• 国内
凤凰网 敦煌网 豆丁
人工编的名词索引-方便查找
全文索引结构
词: 文档:
北京 上海 武汉
1
2
3
天津 大连
4
Βιβλιοθήκη Baidu
5
Lucene中的倒排索引
索引相关类
Document Field(URL) Field(Title) Field(Body) Analyzer IndexWriter
index.optimize();//索引优化 index.close();//关闭索引库
向索引增加文档
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);
分类统计(Faceted Search)
Filter实现的分类统计
String[] cats = {"001004003","001008003021","001004014" }; //类别数组
long[] catCounts = new long[cats.length];//分类统计结果
//原始查询 Filter all = new QueryWrapperFilter(q);
• • •
•
•
通过IndexWriter来写索引,通过IndexReader读索引。 一段有意义的文字需要通过Analyzer分割成一个个词语后才能按关键词搜索。 Analyzer就是分析器,StandardAnalyzer是Lucene中最常用的分析器。 TokenStream实例保存着当前的Attribute状态。 Attribute 是一个接口,实 现中包含一个代表词本身含义的字符串和该词在文章中相应的起止偏移位置, Attribute还可以用来存储词类型或语义信息。 一个Document代表索引库中的一条记录。要搜索的信息封装成Document 后通过IndexWriter写入索引库。调用Searcher接口按关键词搜索后,返回的也是 一个封装后的Document的列表。 一个Document可以包含多个列,叫做field。例如一篇文章可以包含“标 题”、“正文”、“修改时间”等field,创建这些列对象以后,可以通过 Document的add方法增加这些列。