lucene 查询示例

本文是我们名为“ Apache Lucene基础知识 ”的学院课程的一部分。

在本课程中,您将了解Lucene。 您将了解为什么这样的库很重要,然后了解Lucene中搜索的工作方式。 此外,您将学习如何将Lucene Search集成到您自己的应用程序中,以提供强大的搜索功能。 在这里查看 !

目录

1.引言 2.Lucene查询 3,Lucene查询API 4,基本搜索
4.1。条款 4.2。通配符查询 4.3。布尔运算符 4.3分组 4.4。短语查询 4.5。范围查询 4.6。前缀查询 4.7。模糊查询

1.引言

在上一章中,我们了解了Lucene搜索引擎的不同组件 。 我们还使用lucene索引和搜索程序构建了一个小型搜索应用程序。 在本章中,我们将讨论Lucene查询。

2.Lucene查询

Lucene具有用于查询其索引的自定义查询语法。 查询分为术语和运算符。 术语有两种类型: 1 . 单词2.短语 。 单个术语是一个单词,例如“测试”或“样本”。 词组是一组用双引号括起来的单词,例如“ welcome lucene”。 可以将多个术语与布尔运算符组合在一起以形成更复杂的查询。 对于Lucene Java,TermQuery是最原始的查询。 然后是BooleanQuery,PhraseQuery和许多其他Query子类可供选择。

字段执行搜索时,我们可以指定要搜索的字段。任何现有的字段名称都可以用作字段名称。 语法为FieldName:VALUE 。 有一些特殊的字段类型具有自己的语法来定义查询词。 例如,DateTime:ModificationDate:>'2010-09-01 12:00:00'我们将在后面的部分中解释对这些字段的搜索操作。

3,Lucene查询API

当Lucene的QueryParser解析人类可读的查询时,它将转换为Query类的单个具体子类。 我们需要对基础的具体Query子类有所了解。 下表列出了相关的子类,它们的用途以及一些示例表达式:

查询实施 目的 样本表达
TermQuery 单项查询,实际上是一个单词。 雷诺
PhraseQuery 多个项的顺序匹配或彼此接近的匹配项 “前方点亮”
RangeQuery 用开始和结束词之间(包括或排除端点)的词来匹配文档。 [A到Z]

{A到Z}

WildcardQuery 轻量级的,类似于正则表达式的术语匹配语法。 j * v?

f ?? bar

PrefixQuery 匹配以指定字符串开头的所有术语。 起司*
FuzzyQuery Levenshtein紧密匹配算法。 树〜
BooleanQuery 将其他Query实例聚合为允许AND,OR和NOT逻辑的复杂表达式。 雷诺和“前方点亮”

奶酪*-奶酪

所有这些Query实现都在org.apache.lucene.search包中。 BooleanQuery是一种特殊情况,因为它是一个聚合其他查询(包括用于复杂表达式的嵌套BooleanQuery )的Query容器。

这是一个基于查询片段的BooleanQuery 。 在这里,我们可以看到QueryParser创建的查询与API创建的查询等效:

public class RulezTest extends TestCase { public void testJavaNotDotNet() throws Exception { BooleanQuery apiQuery = new BooleanQuery(); apiQuery.add(new TermQuery(new Term("contents", "java")), true, false); apiQuery.add(new TermQuery(new Term("contents", "net")), true, false); apiQuery.add(new TermQuery(new Term("contents", "dot")), false, true); Query qpQuery = QueryParser.parse("java AND net NOT dot", "contents", new StandardAnalyzer()); // Query and subclasses behave as expected with .equals assertEquals(qpQuery, apiQuery); }
}

Query类的一些有趣的功能是它们的toString方法。 每个Query子类都会生成等效的QueryParserexpression (尽管不一定在文本上精确)。 有两种变体:一种是标准的Object.toString重写方法,另一种接受默认字段名称。 下面的测试案例演示了这两种方法的工作原理,并说明了如何返回等效(但不是确切)的表达式。

public void testToString() throws Exception { Query query = QueryParser.parse("java AND net NOT dot", "contents", new StandardAnalyzer()); assertEquals("+java +net -dot", query.toString("contents")); assertEquals("+contents:java +contents:net -contents:dot", query.toString());
}

注意,解析的表达式是“ java AND net NOT dot”,但是从toString方法返回的表达式使用了缩写语法“ + java + net -dot”。 我们的第一个测试用例( testJavaNotDotNet )证明了底层查询对象本身是等效的。

no-arg toString方法不对每个术语的字段名称做任何假设,并使用字段选择器语法明确指定它们。 使用这些toString方法可方便地诊断QueryParser问题。

4,基本搜索

在大多数情况下,您要查找单个术语或短语,即由双引号引起的一组单词(“示例应用程序”)。 在这些情况下,我们将在默认索引数据中查找包含这些单词的内容,这些默认索引数据包含内容的所有相关文本。

在更复杂的情况下,我们可能需要根据要查找的内容的类型或位置进行某些过滤,或者我们要在特定字段中进行搜索。 在这里,我们可以学习如何构建更复杂的查询,这些查询可用于有效地在大型存储库中查找内容。

4.1。条款

假设我们要在标签字段中使用关键字“博客”进行搜索。 语法将是

tag :  blog

现在,我们将在标签字段中搜索短语“ lucene blog”。 为此,语法将是

tag :   "lucene blog"

现在,让我们在标签字段中搜索“ lucene blog”,然后在正文中搜索“ technical blog”,

tag : "lucene blog" AND body : "technical blog"

假设我们要在标签字段中搜索短语“ lucene blog”,在正文中搜索“技术博客”,或者在标签字段中搜索“ searching blog”,

(tag : "lucene blog" AND body : "technical blog") OR tag : "searching blog"

如果我们想在标签字段中搜索“博客”而不是“ lucene”,则语法看起来会相似,

tag : blog -tag : lucene

4.2。通配符查询

Lucene支持在单个术语(而不是短语查询)中的单字符和多字符通配符搜索。

  1. 要执行单个字符通配符搜索,请使用“?” 符号。
  2. 要执行多字符通配符搜索,请使用“ *”符号。

单字符通配符搜索将查找与替换了单个字符的词相匹配的术语。 例如,要搜索“文本”或“测试”,我们可以使用搜索:te?t

多字符通配符搜索将查找0个或多个字符。 例如,要搜索测试,测试或测试员,我们可以使用搜索:

test*

我们还可以在术语中间使用通配符搜索。

te*t

这是Lucene通配符搜索的示例,

假设我们在“文件”目录中有两个文件。

  1. test-foods.txt

    以下是Deron喜欢的一些食物:

    hamburger
    french fries
    steak mushrooms artichokes

  2. sample-food.txt

    以下是妮可喜欢的一些食物:

    apples
    bananas
    salad mushrooms cheese

现在,我们看一下LuceneWildcardQueryDemo类。 此类基于上述文本文件通过createIndex()方法创建索引,此后,它尝试对该索引执行8个通配符搜索。 使用WildcardQuery类执行其中四个搜索,而使用QueryParser类执行其他四个搜索。

首先使用createIndex()方法对以上两个文件建立索引。

public static void createIndex() throws CorruptIndexException, LockObtainFailedException, IOException {Analyzer analyzer = new StandardAnalyzer();boolean recreateIndexIfExists = true;IndexWriter indexWriter = new IndexWriter(INDEX_DIRECTORY, analyzer, recreateIndexIfExists);File dir = new File(FILES_TO_INDEX_DIRECTORY);File[] files = dir.listFiles();for (File file : files) {Document document = new Document();String path = file.getCanonicalPath();document.add(new Field(FIELD_PATH, path, Field.Store.YES, Field.Index.UN_TOKENIZED));Reader reader = new FileReader(file);document.add(new Field(FIELD_CONTENTS, reader));indexWriter.addDocument(document);}indexWriter.optimize();indexWriter.close();
}

为了使用查询解析器执行搜索操作,我们可以添加一个名为searchIndexWithQueryParser()的方法,

public static void searchIndexWithQueryParser(String whichField, String searchString) throws IOException,ParseException {System.out.println("\\nSearching for '" + searchString + "' using QueryParser");Directory directory = FSDirectory.getDirectory(INDEX_DIRECTORY);IndexSearcher indexSearcher = new IndexSearcher(directory);QueryParser queryParser = new QueryParser(whichField, new StandardAnalyzer());Query query = queryParser.parse(searchString);System.out.println("Type of query: " + query.getClass().getSimpleName());Hits hits = indexSearcher.search(query);displayHits(hits);
}

使用以下代码在searchIndexWithWildcardQuery()方法中执行WildcardQuery查询:

Directory directory = FSDirectory.getDirectory(INDEX_DIRECTORY); IndexSearcher indexSearcher = new IndexSearcher(directory); Term term = new Term(whichField, searchString); Query query = new WildcardQuery(term); Hits hits = indexSearcher.search(query);

QueryParser查询通过以下方式在searchIndexWithQueryParser()方法中执行:

Directory directory = FSDirectory.getDirectory(INDEX_DIRECTORY); IndexSearcher indexSearcher = new IndexSearcher(directory); QueryParser queryParser = new QueryParser(whichField, new StandardAnalyzer()); Query query = queryParser.parse(searchString); Hits hits = indexSearcher.search(query);

从我们的main()方法可以看到, LuceneWildcardQueryDemo类执行八个通配符搜索:

searchIndexWithWildcardQuery(FIELD_CONTENTS, "t*t"); searchIndexWithQueryParser(FIELD_CONTENTS, "t*t"); searchIndexWithWildcardQuery(FIELD_CONTENTS, "sam*"); searchIndexWithQueryParser(FIELD_CONTENTS, "sam*"); searchIndexWithWildcardQuery(FIELD_CONTENTS, "te?t"); searchIndexWithQueryParser(FIELD_CONTENTS, "te?t"); searchIndexWithWildcardQuery(FIELD_CONTENTS, "*est"); try { searchIndexWithQueryParser(FIELD_CONTENTS, "*est"); } catch (ParseException pe) { pe.printStackTrace(); }

最后,我们将使用类似的方法打印每次搜索操作的命中数,

public static void displayHits(Hits hits) throws CorruptIndexException, IOException {System.out.println("Number of hits: " + hits.length());Iterator<Hit> it = hits.iterator();while (it.hasNext()) {Hit hit = it.next();Document document = hit.getDocument();String path = document.get(FIELD_PATH);System.out.println("Hit: " + path);}
}

如果我们运行上面的代码,它将向我们显示,

Searching for 't*t' using WildcardQuery
Number of hits: 1
Hit: /home/debarshi/workspace/Test/filesToIndex/test-foods.txt
Searching for 't*t' using QueryParser
Type of query: WildcardQuery
Number of hits: 1
Hit: /home/debarshi/workspace/Test/filesToIndex/test-foods.txt
Searching for 'sam*' using WildcardQuery
Number of hits: 1
Hit: /home/debarshi/workspace/Test/filesToIndex/sample-foods.txt
Searching for 'sam*' using QueryParser
Type of query: PrefixQuery
Number of hits: 1
Hit: /home/debarshi/workspace/Test/filesToIndex/sample-foods.txt
Searching for 'te?t' using WildcardQuery
Number of hits: 1
Hit: /home/debarshi/workspace/Test/filesToIndex/test-foods.txt
Searching for 'te?t' using QueryParser
Type of query: WildcardQuery
Number of hits: 1
Hit: /home/debarshi/workspace/Test/filesToIndex/test-foods.txt
Searching for '*est' using WildcardQuery
Number of hits: 1
Hit: /home/debarshi/workspace/Test/filesToIndex/test-foods.txt
Searching for '*est' using QueryParserorg.apache.lucene.queryParser.ParseException: Cannot parse '*est': '*' or '?' not allowed as first character in WildcardQuery at org.apache.lucene.queryParser.QueryParser.parse(QueryParser.java:175) at LuceneWildcardQueryDemo.searchIndexWithQueryParser(LuceneWildcardQueryDemo.java:81) at LuceneWildcardQueryDemo.main(LuceneWildcardQueryDemo.java:46)
  1. 第一个查询使用带有“ t * t”的WildcardQuery对象。 由于“ t * t”与索引中的“ test”匹配,因此此查询返回1次匹配。
  2. 第二个查询使用QueryParser查询“ t * t”。 QueryParser parse()方法返回WildcardQuery ,并且该查询返回1个匹配项,因为它与第一个查询基本相同。
  3. 第三个查询使用带有“ sam *”的WildcardQuery对象。 由于“ sam *”与“ sample”匹配,因此该通配符查询获得了一次成功。
  4. 第四个查询使用带有“ sam *”的QueryParser 。 但是请注意,QueryParser的parse()方法返回PrefixQuery而不是WildcardQuery 。 由于星号在“ sam *”的末尾。 由于“ sam *”与“ sample”匹配,因此该针对“ sam *”的PrefixQuery命中。
  5. 第五个查询是WildcardQuery ,它在其搜索词“ te?t”中使用问号。 问号可以匹配一个字符。 由于“ te?t”与“ test”匹配,因此搜索返回1个匹配项。
  6. 第六个查询使用带有“ te?t”的QueryParser 。 QueryParser parse()方法返回WildcardQuery ,并且与第五个查询一样,它获得成功。
  7. 第七个查询是“ * est”的WildcardQuery查询。 由于“ test”匹配“ * est”,因此它收到一个匹配。 通常,在第一个字符为通配符的情况下执行查询不是一个好主意。
  8. 第八个查询是“ * est”的QueryParser查询。 请注意, QueryParser对象甚至不允许我们执行第一个字符为星号的查询。 它抛出一个解析异常。

4.3。布尔运算符

布尔运算符允许通过逻辑运算符组合术语。 Lucene支持AND,“ +”,OR,NOT和“-”作为布尔运算符(注意:布尔运算符必须为ALL CAPS)。

OR运算符是默认的合取运算符。 这意味着,如果两个术语之间没有布尔运算符,则使用OR运算符。 OR运算符链接两个术语,如果文档中存在两个术语中的任何一个,则查找匹配的文档。 这等效于使用集的并集。 符号|| 可以代替单词OR。

要搜索包含“ jakarta apache”或仅包含“ jakarta”的文档,请使用查询:

"jakarta apache" jakarta

要么

"jakarta apache" OR jakarta

AND运算符匹配两个术语都存在于单个文档的文本中任何位置的文档。 这等效于使用集合的交点。 可以使用符号&&代替单词AND。

要搜索包含“ jakarta apache”和“ Apache Lucene”的文档,请使用查询:

"jakarta apache" AND "Apache Lucene"

+

“ +”或必需的运算符要求“ +”符号后的术语存在于单个文档的字段中。

要搜索必须包含“ jakarta”且可能包含“ lucene”的文档,请使用以下查询:

+jakarta lucene

NOT运算符排除包含NOT之后的术语的文档。 这等效于使用集的区别。 符号! 可以代替“非”一词使用。

要搜索包含“ jakarta apache”但不包含“ Apache Lucene”的文档,请使用以下查询:

"jakarta apache" NOT "Apache Lucene"

注意:NOT运算符不能仅使用一个术语。 例如,以下搜索将不返回任何结果:

NOT "jakarta apache"

“-”

“-”或禁止运算符排除包含在“-”符号后的术语的文档。

要搜索包含“ jakarta apache”但不包含“ Apache Lucene”的文档,请使用以下查询:

"jakarta apache" -"Apache Lucene"

4.3分组

Lucene支持使用括号将子句分组以形成子查询。 如果要控制查询的布尔逻辑,这可能非常有用。

要搜索“ jakarta”或“ apache”和“网站”,请使用查询:

(jakarta OR apache) AND website

这样可以消除任何混乱,并确保您必须存在该网站,并且可能存在“雅加达”或“ apache”一词。

现场分组

Lucene支持使用括号将多个子句分组到一个字段中。

要搜索包含单词“ return”和短语“ pink panther”的标题,请使用以下查询:

title:(+return +"pink panther")

转义特殊字符

Lucene支持转义查询语法中包含的特殊字符。 当前列表的特殊字符为:

+ – && || ! (){} [] ^”〜*吗? :\

要转义这些字符,请在字符前使用“ \”(反斜杠)。 例如,要搜索(1 + 1):2,请使用查询:

\\(1\\+1\\)\\:2

4.4。短语查询

Lucene中的PhraseQuery匹配包含特定术语序列的文档。 PhraseQuery使用存储在索引中的术语的位置信息。

查询短语中单词之间允许的其他单词的数量称为“斜率”。 可以通过调用setSlop方法进行设置。 如果为零,则为精确短语搜索。 对于较大的值,其工作方式类似于WITHIN或NEAR运算符。

斜率实际上是一个编辑距离,其中单位对应于查询短语中词条移动的位置。 例如,要切换两个单词的顺序需要两个步骤(第一个步骤将单词彼此放在首位),因此要允许对短语进行重新排序,斜率必须至少为两个。

得分更高的比赛要比更差劲的比赛得分高,因此搜索结果将按照准确性进行排序。 默认情况下,斜率为零,要求完全匹配。

PhraseQuery还支持多个术语短语。

短语查询可以与其他术语组合,也可以与BooleanQuery组合使用。 默认情况下,子句的最大数量限制为1,024。

在前面的Lucene通配符查询示例中,我们已经基于两个文本文件完成了搜索操作。 现在,我们将尝试在lucene中使用PhraseQuery查找匹配的短语。

为此,我们将引入一个新方法searchIndexWithPhraseQuery()来代替searchIndexWithWildcardQuery()方法,该方法采用两个字符串表示文档中的单词和searchIndexWithPhraseQuery()值。 它通过基于“ contents”字段以及string1和string2参数添加两个Term对象来构造PhraseQuery 。 然后,它使用setSlop()方法设置PhraseQuery对象的setSlop()值。 通过将PhraseQuery对象传递给IndexSearcher的search()方法进行search() 。 这是代码,

public static void searchIndexWithPhraseQuery(String string1, String string2, int slop) throws IOException,ParseException {Directory directory =     FSDirectory.getDirectory(INDEX_DIRECTORY);IndexSearcher indexSearcher = new IndexSearcher(directory);Term term1 = new Term(FIELD_CONTENTS, string1);Term term2 = new Term(FIELD_CONTENTS, string2);PhraseQuery phraseQuery = new PhraseQuery();phraseQuery.add(term1);phraseQuery.add(term2);phraseQuery.setSlop(slop);displayQuery(phraseQuery);Hits hits = indexSearcher.search(phraseQuery);displayHits(hits);
}

而且,我们从main()调用此方法,

searchIndexWithPhraseQuery("french", "fries", 0);searchIndexWithPhraseQuery("hamburger", "steak", 0);searchIndexWithPhraseQuery("hamburger", "steak", 1);searchIndexWithPhraseQuery("hamburger", "steak", 2);searchIndexWithPhraseQuery("hamburger", "steak", 3);searchIndexWithQueryParser("french fries"); // BooleanQuerysearchIndexWithQueryParser("\\"french fries\\""); // PhaseQuerysearchIndexWithQueryParser("\\"hamburger steak\\"~1"); // PhaseQuerysearchIndexWithQueryParser("\\"hamburger steak\\"~2"); // PhaseQuery

第一个查询以斜率0搜索“ french”和“ fries”,这意味着短语搜索最终是对“ french fries”的搜索,其中“ french”和“ fries”彼此相邻。 由于这存在于test-foods.txt中,因此我们获得了1次点击。

在第二个查询中,我们搜索坡度为0的“汉堡”和“牛排”。由于在两个文档中“汉堡”和“牛排”都不相邻,因此命中0。 第三个查询还涉及对“汉堡包”和“牛排”的搜索,但斜率为1。这些单词彼此之间的距离不超过1个单词,因此我们获得0次匹配。

第四个查询以“ 2”的斜率搜索“汉堡”和“牛排”。在test-foods.txt文件中,我们有“……汉堡薯条……”字样。 由于“汉堡”和“牛排”彼此之间不超过两个字,因此我们获得了1分。 第五个短语查询是相同的搜索,但坡度为3。由于“汉堡包”和“牛排”彼此带有三个单词(彼此是两个单词),因此命中率为1。

接下来的四个查询使用QueryParser 。 注意,在第一个QueryParser查询中,我们得到一个BooleanQuery而不是PhraseQuery 。 这是因为我们传递了QueryParser的parse()方法“炸薯条”而不是“ \”炸薯条\””。 如果希望QueryParser生成PhraseQuery,则搜索字符串需要用双引号引起来。 下一个查询确实搜索“ \”炸薯条\”,我们可以看到它生成了一个PhraseQuery (默认PhraseQuery为0),并响应该查询而获得1次PhraseQuery

最后两个QueryParser查询演示了设置倾斜值。 我们可以看到,可以在搜索字符串的双引号后面设置斜率值,并在其后加上斜线号(〜)和斜率号。

4.5。范围查询

与专有术语范围内的文档匹配的Query 。 它允许匹配字段值在RangeQuery指定的下限和上限之间的RangeQuery 。 范围查询可以包含上限,也可以不包括上限和下限。 排序是按字典顺序进行的(按字典顺序排列(排序)的项的集合)。

现在,如果要为Lucene搜索操作实现RangeQuery ,则必须添加一个名为searchIndexWithRangeQuery() ,该方法基本上是一个构造函数,需要Term指示范围的开始, Term指示范围的结束和一个布尔值,指示搜索是包含开始和结束值(“ true”)还是排除开始和结束值(“ false”)。 代码看起来像

public static void searchIndexWithRangeQuery(String whichField, String start, String end, boolean inclusive)throws IOException, ParseException {System.out.println("\\nSearching for range '" + start + " to " + end + "' using RangeQuery");Directory directory = FSDirectory.getDirectory(INDEX_DIRECTORY);IndexSearcher indexSearcher = new IndexSearcher(directory);Term startTerm = new Term(whichField, start);Term endTerm = new Term(whichField, end);Query query = new RangeQuery(startTerm, endTerm, inclusive);Hits hits = indexSearcher.search(query);displayHits(hits);
}

现在我们将调用上述方法,

searchIndexWithRangeQuery(FIELD_LAST_MODIFIED, "2014-04-01-00-00-00", "2014-04-01-23-59-59", INCLUSIVE);searchIndexWithRangeQuery(FIELD_LAST_MODIFIED, "2014-04-02-00-00-00", "2014-04-02-23-59-59", INCLUSIVE);searchIndexWithRangeQuery(FIELD_LAST_MODIFIED, "2014-04-01-00-00-00", "2014-04-01-21-21-02", INCLUSIVE);searchIndexWithRangeQuery(FIELD_LAST_MODIFIED, "2014-04-01-00-00-00", "2014-04-01-21-21-02", EXCLUSIVE);// equivalent range searches using QueryParsersearchIndexWithQueryParser(FIELD_LAST_MODIFIED, "[2014-04-01-00-00-00 TO 2014-04-01-23-59-59]");searchIndexWithQueryParser(FIELD_LAST_MODIFIED, "[2014-04-02-00-00-00 TO 2014-04-02-23-59-59]");searchIndexWithQueryParser(FIELD_LAST_MODIFIED, "[2014-04-01-00-00-00 TO 2014-04-01-21-21-02]");searchIndexWithQueryParser(FIELD_LAST_MODIFIED, "{2014-04-01-00-00-00 TO 2014-04-01-21-21-02}");

最后, createIndex()方法稍有变化。 我们添加了一些实现日期时间的操作,并打印了索引文件的最后修改时间。

在控制台输出的顶部,我们可以看到两个文件都已建立索引,并且这些文件的“最后修改”时间是“ 2014-04-01-21-21-02”(对于test-foods.txt )和“ 2014-04-01-21-21-38”(针对sample-foods.txt)。

在第一个范围查询中,我们搜索所有在2014年4月1日最后一次修改的文件。由于两个文件在该日期最后一次修改,这将返回2次匹配。 在第二个范围查询中,我们搜索所有在2014年4月2日最后一次修改的文件。由于两个文档都在2014年4月1日最后一次修改,因此返回0次匹配。

接下来,我们在2014年4月1日至2014年4月1日(含2014年)之间进行搜索。 由于test-foods.txt的上次修改时间为2014-04-01-21-21-02,并且范围查询包含此值,因此我们得到了一个搜索结果。 之后,我们仅在2014-04-01-00-00-00到2014-04-01-21-21-02之间进行搜索。 由于test-foods.txt的上一次修改时间为2014-04-01-21-21-02,并且范围查询不包含此值(因为已将其排除在外),因此此搜索返回0个匹配。

此后,接下来的四个搜索显示使用QueryParser对象执行的等效搜索。 请注意,对于每个查询,QueryParser的parse()方法都返回ConstantScoreRangeQuery对象而不是RangeQuery对象,正如我们从这些查询的控制台输出中看到的那样。

4.6。前缀查询

与包含带有指定前缀的术语的文档匹配的QueryPrefixQueryQueryParser构建,用于类似nam *的输入。

我们将尝试使用两个文本文件(test-foods.txt和sample-foods.txt)使用前缀查询来搜索带有其前缀的特定术语。

对于这样做,我们将增加一个名为方法searchIndexWithPrefixQuery()将搜索器的索引(这将创建createIndex()使用PrefixQuery 。 此方法有两个参数,一个是字段名,另一个是搜索字符串。

public static void searchIndexWithPrefixQuery(String whichField, String searchString) throws IOException,ParseException {System.out.println("\\nSearching for '" + searchString + "' using PrefixQuery");Directory directory = FSDirectory.getDirectory(INDEX_DIRECTORY);IndexSearcher indexSearcher = new IndexSearcher(directory);Term term = new Term(whichField, searchString);Query query = new PrefixQuery(term);Hits hits = indexSearcher.search(query);displayHits(hits);
}

接下来,我们将从程序的main()方法中调用此方法–

searchIndexWithPrefixQuery(FIELD_CONTENTS, "test");searchIndexWithPrefixQuery(FIELD_CONTENTS, "tes*");

在第一个查询中,查询字符串不包含星号。 因此,如果我们打印QueryParser的parse()方法的查询类型,它将打印TermQuery而不是PrefixQuery

在第二查询中,星号向QueryParser指示这是一个前缀查询,因此它从其parse()方法返回PrefixQuery对象。 这导致在索引内容中搜索前缀“ tes”。 由于“ test”在索引中,因此产生1次匹配。

4.7。模糊查询

模糊查询基于Damerau-Levenshtein(最佳字符串对齐)算法。 FuzzyQuery将术语“接近”匹配到指定的基本术语:我们指定了一个允许的最大编辑距离,并且在与基本术语(然后包含这些术语的文档)相距该编辑距离内的所有术语都将匹配。

QueryParser语法为QueryParserQueryParser ,其中N是允许的最大编辑数量(对于较早的发行版,N是0.0到1.0之间的令人困惑的浮点数,它通过一个棘手的公式转换为等效的最大编辑距离)。

FuzzyQuery非常适合匹配专有名称:我们可以搜索lucene〜1,它将匹配luccene(插入c),lucee(删除n),lukene(用k替换c)和许多其他“接近”术语。 使用最大编辑距离2,我们最多可以有2个插入,删除或替换。 每次比赛的得分均基于该词的编辑距离; 因此完全匹配的得分最高; 编辑距离1,降低; 等等

QueryParser支持在词条上使用尾随波浪号的模糊词条查询。 例如,搜索wuzza〜将找到包含“ fuzzy”和“ wuzzy”的文档。 编辑距离会影响评分,因此较低的编辑距离会获得较高的分数。

翻译自: https://www.javacodegeeks.com/2015/09/advanced-lucene-query-examples.html

lucene 查询示例

lucene 查询示例_高级Lucene查询示例相关推荐

  1. asp多表查询并显示_高级子查询

    要点 1.子查询结果只允许返回单行,子查询包括相关子查询:在主查询中,每查询一条记录,需要重新做一次子查询,这种称为相关子查询.非相关子查询:在主查询中,子查询只需要执行一次,子查询结果不再变化,供主 ...

  2. 预编译sql查询语句_频繁的查询重新编译– SQL查询性能的杀手–简介

    预编译sql查询语句 In this article, we will explain what compilations and recompilations are, and give recom ...

  3. db2嵌套查询效率_提高DB2 查询性能的常用方法

    [IT168 技术文档]本文先对 DB2 提供的几种用于提高查询性能的相关工具和命令进行介绍,然后根据笔者的工作经验介绍一些常用的技巧和方法来提高查询性能.主要集中于如何创建和维护索引.改写查询以及改 ...

  4. db2嵌套查询效率_提高 DB2 查询性能的常用方法

    提高 DB2 查询性能的常用方法 张大为 和 陈力 2007 年 9 月 28 日发布 简介 随着 DB2 应用的逐渐增多,越来越多的数据库开发人员在项目开发过程中都会遇到查询过于复杂,导致性能难以接 ...

  5. 产品防伪码查询系统_学历学籍查询系统_证书查询系统_录取成绩查询系统_工资查询系统_信息查询系统

    本查询系统是一个万能自助式查询系统,可以根据需要生成自己需要的查询系统,如:产品防伪码查询系统.学历学籍查询系统.证书查询系统.录取成绩查询系统.工资查询系统.教师学生信息查询系统等等. 价格:200 ...

  6. mysql高级查询面试_高级MySQL数据库面试问题 附答案

    因为有大家的支持,我们才能做到现在,感谢你们这一路上对我们的支持.在这篇文章中,我们将主要针对MySQL的实用技巧,讲讲面试中相关的问题. 1. 如何使用SELECT语句找到你正在运行的服务器的版本并 ...

  7. lucene学习笔记_学习Lucene

    lucene学习笔记 我目前正在与一个团队合作,开始一个基于Lucene的新项目. 虽然大多数时候我会争论使用Solr还是Elasticsearch而不是简单的Lucene,但这是一个有意识的决定. ...

  8. lucene快速入门_为Lucene选择快速唯一标识符(UUID)

    lucene快速入门 大多数使用Apache Lucene的搜索应用程序都会为每个索引文档分配一个唯一的ID(即主键). 尽管Lucene本身不需要这样做(它可能不太在乎!),但应用程序通常需要它以后 ...

  9. trackingmore快递查询平台_国际快递查询app下载-Trackingmore 安卓版v1.7.4-PC6安卓网

    Trackingmore国际快递查询应用app是一款生活服务应用,是东方之舟网络推出的免费快递查询工具.另外Trackingmore国际快递查询应用app还支持国内多家快递公司的查询服务,让用户们轻松 ...

最新文章

  1. 深入浅出python机器学习_4.3.1_岭回归的原理 4.3.2_岭回归的参数调节
  2. 分析Android studio3.0的instant run开启关闭对APK大小的影响
  3. wepy组件子父传值_【WePY小程序框架实战三】-组件传值
  4. IIS7.5和IIS8如何设置FTP的pasv端口范围
  5. AAA验证和ciscorescue v4.2 验证服务器的搭建(telnet方式和级别的设置)
  6. 黑盒测试实践进度记录(五)
  7. jsp 连接sql数据库查询(源代码)
  8. 客户端常见的几种数据传输方法
  9. Vue开发实例(01)之环境搭建nodejs与运行第一个Vue项目
  10. 网络流量监控(局域网)
  11. python中format使用
  12. JAVA——实现求s=a+aa+aaa+aaaa+aa...a的值
  13. yuque-hexo:语雀写文,自动部署 Hexo 博客
  14. 牛客网之黑暗的字符串
  15. python 处理大数据
  16. matlab int double类型,( ) 一个 int 型与一个 double 型数据进行混合运算时,其结果是 double 型。...
  17. css背景图片半透明效果
  18. 统计学(3)——数据抽样方法的细节
  19. 小程序实习生实现手机机型预约
  20. 房山大数据北师大_北京师范大学2019级本科生新生大数据

热门文章

  1. P4707-重返现世【dp,数学期望,扩展min-max容斥】
  2. jzoj3852-单词接龙【0/1分数规划,负环】
  3. jzoj5123-diyiti【统计,容斥】
  4. nssl1141,jzoj3470-最短路【SPFA,暴力】
  5. 【模拟】游戏(jzoj 1614)
  6. P3980 NOI2008志愿者招募
  7. 动态规划训练16 [Doing Homework HDU - 1074 ]
  8. mybatis入门(七)之日志
  9. 一篇文章彻底了解清楚什么是负载均衡
  10. Spring MVC表单防重复提交