Lucene in action 笔记 search篇
一. 用lucene怎么完成search
1. 创建IndexSearcher
IndexSearcher searcher = new IndexSearcher(directory);
2. 生成需要搜索的词
Term t = new Term("subject", "ant");
3. 创建查询
Query query = new TermQuery(t);
4. search并得到结果
Hits hits = searcher.search(query);
此处的query就简单的由term生成的, 对于复杂的query需要用QueryParser来生成
Query query = QueryParser.parse("+JUNIT +ANT -MOCK", "contents", new SimpleAnalyzer());
static public Query parse(String query, String field, Analyzer analyzer) throws ParseException
query: 需要parse的查询string
field: default的field
analyzer: 处理查询string需要的analyzer, 来处理大小写等
二. Using IndexSearcher
1. search
Hits search(Query query) Straightforward searches needing no filtering.
Hits search(Query query, Filter filter) Searches constrained to a subset of available documents, based on filter criteria.
void search(Query query, HitCollector results) Used only when all documents found from a search will be needed.
HitCollector 和 Hits不同, 会包含所有结果, 所以注意这个函数performance问题
2. Working with Hits
Hits应该会记录下所有匹配的结果, 但是只会加载top 100到内存, 因为一般用户也只需要这些. 如果你用doc(n)访问未被cache的文章, 需要先从index里面load, 所以需要时才去调用比较合理.
length() Number of documents in the Hits collection
doc(n) Document instance of the nth top-scoring document
id(n) Document ID of the nth top-scoring document
score(n) Normalized score (based on the score of the topmost document) of the nth topscoring document, guaranteed to be greater than 0 and less than or equal to 1
对于分页显示hits的solution, 推荐每页都从新去做search来生成hits, 并从中取出你所需要的页. 这样符合stateless的服务端的原则
3. Reading indexes into memory
如果你内存足够大, 而且index本身是没有变化的时候
你可以把index载入内存, search将飞快...
RAMDirectory ramDir = new RAMDirectory(dir);
三. Understanding Lucene scoring
至于怎么排名的就不解释了.
这里有个接口可以查看排名的具体细节, 为什么他就排第一个了?
IndexSearcher searcher = new IndexSearcher(directory);
Hits hits = searcher.search(query);
Explanation explanation = searcher.explain(query, hits.id(0));
System.out.println(explanation.toString());
好了通过打出的各个参数的值, 就能理解他为什么排第一个了
四. Creating queries programmatically
用程序的方式取创建查询, 还有一种方法就是用QueryParser去生成查询.
1. Searching by term: TermQuery
Term t = new Term("contents", "java"); Term(field, value)
Query query = new TermQuery(t);
term的value是大小写敏感的, 所以search时的大小写要和index时的一致
2. Searching within a range: RangeQuery
begin = new Term("pubmonth","198805");
end = new Term("pubmonth","198810");
RangeQuery query = new RangeQuery(begin, end, true); 最后这个flag是表示是否包含begin和end
QueryParser中的表示为: [begin TO end] or {begin TO end}.
3. Searching on a string: PrefixQuery
找前缀, 底下这个意思是找到这个目录, 及其所有子目录
Term term = new Term("category", "/technology/computers/programming");
PrefixQuery query = new PrefixQuery(term);
QueryParser中的表示为:prefix*
4. Combining queries: BooleanQuery
TermQuery searchingBooks =new TermQuery(new Term("subject","search"));
RangeQuery currentBooks =new RangeQuery(new Term("pubmonth","200401"), new Term("pubmonth","200412"),true);
BooleanQuery currentSearchingBooks = new BooleanQuery();
currentSearchingBooks.add(searchingBook s, true, false);
currentSearchingBooks.add(currentBooks, true, false);
可见, 可以通过add往booleanquery上加子查询, 并通过最后两个参数来决定与或的关系
两个参数分别是required and prohibited, 就是要求和禁止, 两个不可能全true
false, false: Clause is optional, 即或
true, false: Clause must match, 即与
false, true: Clause must not match, 即非
QueryParser中的表示为: –, +, AND, OR, and NOT
lucene新的接口是:
public void add(Query query, BooleanClause.Occur occur)
where occur can be BooleanClause.Occur.MUST, BooleanClause.Occur.SHOULD or BooleanClause.Occur.MUST_NOT
(AND )BooleanClause.Occur.MUST means exactly that: Only documents matching that clause are considered.
(OR )BooleanClause.Occur.SHOULD means the term is optional.
(NOT )BooleanClause.Occur.MUST_NOT means any documents matching this clause are excluded from the results.
5. 后面还有PhraseQuery, WildcardQuery, FuzzyQuery就不一一介绍了, 大家用到再去查吧
五. Parsing query expressions: QueryParser
虽然用api去创建query很好, 但有时也需要用human-readable textual query representation.
对于一个已有的query, 我们可以用Query.toString, 得到一个query的human-readable textual query representation.
这个就不具体说了, QueryParser看上去不错, 不过他并不能表示所有的查询, 有些查询必须用api生成. 而且用QueryParser去parse应该是要额外耗费一些时间的. 对于要提供给用户查询UI的应用, QueryParser是非常方便的.
本文章摘自博客园,原文发布日期:2011-07-04
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的