一、查询语法介绍
Lucene是一个全文搜索引擎,它的查询语法基于一种称为查询表达式(query expression)的格式。一个查询表达式由一系列的项和运算符组合而成,用于从文本中检索需要的内容。下面是一些常用的运算符:
Operator | Example | Meaning
===========================================================
AND | A AND B | 匹配同时包含A和B的文档
OR | A OR B | 匹配包含A或B的文档
NOT | A NOT B | 匹配包含A但不包含B的文档
+ | +A +B | 匹配同时包含A和B的文档(+是AND的缩写)
- | A -B | 匹配包含A但不包含B的文档(-是NOT的缩写)
() | (A OR B)AND C | 改变操作符之间的优先级,这里匹配包含A或B,并且包含C的文档
还有一些高级运算符,如模糊匹配~(可以使用一个数字指定最大编辑距离)、通配符*和?等,这些运算符可用于更高级的搜索需求。当然,查询语法远远不止这些,下面将逐一介绍相关的内容。
二、单项匹配查询
在Lucene中,一个查询表达式由多个项组成,一个项可以是单词、短语、数字等。最简单的,也是最常见的查询类型就是单项匹配查询。
Query query = new TermQuery(new Term("content", "Lucene"));
TopDocs hits = searcher.search(query, 10);
在这个查询中,我们指定了要匹配内容域(content)中包含单词“Lucene”的文档。
三、多项匹配查询
除了单项匹配查询,我们也可以对多个项进行匹配,例如一个查询表达式“A AND B”就将匹配同时包含单词A和B的文档。
Query query = new BooleanQuery.Builder()
.add(new TermQuery(new Term("title", "Lucene")), BooleanClause.Occur.SHOULD)
.add(new TermQuery(new Term("content", "Lucene")), BooleanClause.Occur.SHOULD)
.build();
TopDocs hits = searcher.search(query, 10);
在这个查询中,我们要匹配标题域(title)中或内容域(content)中包含单词“Lucene”的文档。
四、短语匹配查询
短语匹配查询是一种更加精确的查询方式,只匹配在指定的距离内出现的短语。
Query query = new PhraseQuery.Builder()
.add(new Term("content", "Lucene"))
.add(new Term("content", "search"))
.setSlop(2)
.build();
TopDocs hits = searcher.search(query, 10);
在这个查询中,我们要匹配在内容域(content)中,同时包含单词“Lucene”和“search”的文档,并且这两个单词之间的最大距离是2。
五、通配符匹配查询
对于需要匹配一定模式的查询,我们可以使用通配符匹配查询。在Lucene中,支持两种通配符:和?,其中代表任意多个字符,?代表任意一个字符。
Query query = new WildcardQuery(new Term("content", "L*cene"));
TopDocs hits = searcher.search(query, 10);
在这个查询中,我们要匹配在内容域(content)中,以L开头,ene结尾,中间可以有任意多个字符的文档。
六、模糊匹配查询
如果我们需要匹配一些拼写错误的查询,或者由于OCR识别等原因而导致的一些文本输入错误,我们可以使用模糊匹配查询。
Query query = new FuzzyQuery(new Term("content", "Luceen"), 2);
TopDocs hits = searcher.search(query, 10);
在这个查询中,我们要匹配在内容域(content)中,与单词“Luceen”最多只有2个编辑距离的文档。编辑距离指的是两个单词之间需要进行的插入、删除或替换操作次数。
七、范围匹配查询
除了上面的所有查询方式,我们还可以进行范围匹配查询,用来匹配符合一定范围的项。
Query query = IntPoint.newRangeQuery("price", 500, 1000);
TopDocs hits = searcher.search(query, 10);
在这个查询中,我们要匹配在价格域(price)中,值在500到1000之间的文档。
八、排序查询和分页查询
在实际使用中,我们往往需要对查询结果进行排序和分页展示。Lucene提供了非常方便的API让我们实现这些功能。 这里介绍一个例子:我们想要对内容域(content)进行单项匹配查询,并按照得分值降序排序,然后展示第11页到第20页的查询结果。
Query query = new TermQuery(new Term("content", "Lucene"));
Sort sort = new Sort(SortField.FIELD_SCORE);
int hitsPerPage = 10;
int start = 10 * (page - 1);
TopDocs hits = searcher.search(query, start + hitsPerPage, sort);
ScoreDoc[] scoreDocs = hits.scoreDocs;
for (int i = start; i < Math.min(scoreDocs.length, start + hitsPerPage); i++) {
Document doc = searcher.doc(scoreDocs[i].doc);
System.out.println("docId=" + scoreDocs[i].doc + ", score=" + scoreDocs[i].score + ", content=" + doc.get("content"));
}
这段代码首先定义了查询表达式,然后根据得分值对查询结果进行排序,并指定展示的页码和每页的数量。最后,我们遍历结果,打印每个匹配文档的ID、得分值和内容。