lucene 查询示例_Lucene查询(搜索)语法示例
lucene 查詢示例
本文是我們名為“ Apache Lucene基礎(chǔ)知識 ”的學(xué)院課程的一部分。
在本課程中,您將了解Lucene。 您將了解為什么這樣的庫很重要,然后了解Lucene中搜索的工作方式。 此外,您將學(xué)習(xí)如何將Lucene Search集成到您自己的應(yīng)用程序中,以提供強大的搜索功能。 在這里查看 !
目錄
1.簡介 2.查詢類1.簡介
在本課程的這一課中,我們將研究Lucene提供的基本查詢機制。 您可能會在入門課程中記得,Lucene不會將要搜索的原始文本發(fā)送到索引。 為此,它使用Query對象。 在本課程中,我們將看到所有關(guān)鍵要素,它們將人類書面搜索短語轉(zhuǎn)換為諸如Queries類的代表性結(jié)構(gòu)。
2.查詢類
Query類是一個公共抽象類,它代表對索引的查詢。 在本節(jié)中,我們將看到最重要的Query子類,您可以使用它們來執(zhí)行高度定制的查詢。
2.1術(shù)語查詢
這是您可以針對Lucene索引執(zhí)行的最簡單直接的查詢。 您只需搜索在特定Field包含單個單詞的Documents 。
基本的TermQuery構(gòu)造函數(shù)定義如下: public TermQuery(Term t) 。 您從第一節(jié)課中記得, Term由兩部分組成:
因此,如果您想創(chuàng)建一個TermQuery來查找所有在"content" Field中包含"good"字樣的Documents ,則可以按照以下方法進行操作
TermQuery termQuery = new TermQuery(new Term("content","good"));我們可以使用它在先前創(chuàng)建的索引中搜索單詞“ static”:
String q = "static"Directory directory = FSDirectory.open(indexDir);IndexReader indexReader = DirectoryReader.open(directory);IndexSearcher searcher = new IndexSearcher(indexReader);Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_46);TermQuery termQuery = new TermQuery(new Term("content",q));TopDocs topDocs =searcher.search(termQuery, maxHits);ScoreDoc[] hits = topDocs.scoreDocs;for (ScoreDoc hit : hits) {int docId = hit.doc;Document d = searcher.doc(docId);System.out.println(d.get("fileName") + " Score :" + hit.score); }System.out.println("Found " + hits.length);輸出為:
C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\Product.java Score :0.29545835 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\SimpleSearcher.java Score :0.27245367 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\PropertyObject.java Score :0.24368995 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\SimpleIndexer.java Score :0.14772917 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\TestSerlvet.java Score :0.14621398 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\ShoppingCartServlet.java Score :0.13785185 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\MyServlet.java Score :0.12184498 Found 7如您所見,我的七個源文件中包含"static"關(guān)鍵字。 就是這樣。 自然,如果您嘗試在查詢字符串中添加另一個單詞,搜索將返回0個結(jié)果。 例如,如果您將查詢字符串設(shè)置為:
String q = "private static"輸出為:
Found 0現(xiàn)在,我知道我的許多源文件中都存在"private static" 。 但是,您可能還記得,我們在索引過程中使用了StandarAnalyzer處理從文件中檢索的純文本。 StandardAnalyzer將文本拆分為單個單詞,因此每個Term包含一個單詞。 您可以選擇不標(biāo)記索引的Field 。 但是我建議您在包含元數(shù)據(jù)的Fields中執(zhí)行此操作,而不是在包含其內(nèi)容的字段中,這些字段包含有關(guān)文檔的信息(例如標(biāo)題或作者)。 例如,如果您選擇不對名稱為'author'且值為'James Wilslow'的Field進行標(biāo)記化并編制索引,則Field 'author'將僅包含一個整體值為'James Wilslow' Term 。 如果您對Field進行了標(biāo)記化,則它將包含兩個Terms ,一個的值為'James' ,另一個的值為'Wilslow' 。
2.2短語查詢
使用PhraseQuery您可以搜索包含特定單詞序列(又名短語)的Documents 。
您可以這樣創(chuàng)建一個PhraseQuery :
PhraseQuery phraseQuery = new PhraseQuery();然后您可以向其添加Terms 。 例如,如果您要搜索在其“內(nèi)容”字段中包含短語“ private static”的Documents ,則可以這樣做:
PhraseQuery phraseQuery = new PhraseQuery();phraseQuery.add(new Term("content","private")); phraseQuery.add(new Term("content","static"));TopDocs topDocs =searcher.search(phraseQuery, maxHits);ScoreDoc[] hits = topDocs.scoreDocs;for (ScoreDoc hit : hits) {int docId = hit.doc;Document d = searcher.doc(docId);System.out.println(d.get("fileName") + " Score :" + hit.score); }System.out.println("Found " + hits.length);輸出為:
C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\Product.java Score :0.54864377 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\PropertyObject.java Score :0.45251375 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\SimpleSearcher.java Score :0.45251375 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\TestSerlvet.java Score :0.27150828 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\ShoppingCartServlet.java Score :0.25598043 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\MyServlet.java Score :0.22625688 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\SimpleIndexer.java Score :0.22398287 Found 7僅當(dāng)“ Field "static"連續(xù)且以準(zhǔn)確順序同時包含單詞"private"和"static" , Document才進入結(jié)果。
因此,如果您以上述方式更改上面的代碼:
phraseQuery.add(new Term("content","private")); phraseQuery.add(new Term("content","final"));你會得到 :
Found 0這是因為盡管我的源文件包含兩個詞,但它們不是連續(xù)的。 要改變這種行為一點點,你可以添加一個slop到PhraseQuery 。 當(dāng)斜率增加1時,您最多允許一個詞插入詞組中的詞之間。 添加坡度2時,短語中的單詞之間最多允許2個單詞。
有趣的是: “實際上,坡度是一個編輯距離,其單位對應(yīng)于查詢短語中詞條移動的位置。 例如,要切換兩個單詞的順序需要兩個步驟(第一個步驟將單詞彼此放在首位),因此要允許對短語進行重新排序,斜率必須至少為兩個。
因此,如果這樣做:
PhraseQuery phraseQuery = new PhraseQuery();phraseQuery.add(new Term("content","private")); phraseQuery.add(new Term("content","final"));phraseQuery.setSlop(2);我們的搜索輸出將給出:
C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\Product.java Score :0.38794976 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\PropertyObject.java Score :0.31997555 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\SimpleSearcher.java Score :0.31997555 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\TestSerlvet.java Score :0.19198532 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\ShoppingCartServlet.java Score :0.18100551 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\MyServlet.java Score :0.15998778 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\SimpleIndexer.java Score :0.15837982重要的是要提到包含更接近查詢確切短語的短語的文檔將獲得更高的分?jǐn)?shù)。
2.3布爾查詢
BooleanQuery是一種更具表現(xiàn)力和功能的工具,因為您可以將多個查詢與布爾子句結(jié)合在一起。 可以使用BooleanClauses填充BoleanQuery。 BooleanClause包含一個Query ,以及Query在布爾搜索中應(yīng)具有的角色。
更具體地說,布爾子句可以在查詢中扮演以下角色:
如果僅使用SHOULD子句進行布爾查詢,則結(jié)果至少匹配其中一個子句。 這看起來像經(jīng)典的OR布爾運算符,但正確使用它并不是那么簡單。
現(xiàn)在讓我們看一些例子。 讓我們找到包含單詞“ string”但不包含單詞“ int”的源文件。
TermQuery termQuery = new TermQuery(new Term("content","string")); TermQuery termQuery2 = new TermQuery(new Term("content","int"));BooleanClause booleanClause1 = new BooleanClause(termQuery, BooleanClause.Occur.MUST); BooleanClause booleanClause2 = new BooleanClause(termQuery2, BooleanClause.Occur.MUST_NOT);BooleanQuery booleanQuery = new BooleanQuery(); booleanQuery.add(booleanClause1); booleanQuery.add(booleanClause2);TopDocs topDocs =searcher.search(booleanQuery, maxHits);結(jié)果如下:
C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\SimpleEJB.java Score :0.45057273 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\PropertyObject.java Score :0.39020744 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\ShoppingCartServlet.java Score :0.20150226 C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\TestSerlvet.java Score :0.13517183 Found 4現(xiàn)在,讓我們嘗試查找包含單詞“ nikos”和短語“ httpservletresponse response”的所有文檔。 在以下代碼片段中,您可以看到如何避免創(chuàng)建BooleanClause實例,從而使您的代碼更緊湊。
TermQuery termQuery = new TermQuery(new Term("content","nikos"));PhraseQuery phraseQuery = new PhraseQuery(); phraseQuery.add(new Term("content","httpservletresponse")); phraseQuery.add(new Term("content","response"));BooleanQuery booleanQuery = new BooleanQuery();booleanQuery.add(phraseQuery,BooleanClause.Occur.MUST); booleanQuery.add(termQuery,BooleanClause.Occur.MUST);TopDocs topDocs =searcher.search(booleanQuery, maxHits);結(jié)果如下:
C:\\Users\\nikos\\Desktop\\LuceneFolders\\LuceneHelloWorld\\SourceFiles\\ShoppingCartServlet.java Score :0.3148332 Found 1讓我們找到所有包含單詞“ int”或單詞“ nikos”的文檔。當(dāng)您可能要成像時,必須以某種方式使用SHOULD規(guī)范:
TermQuery termQuery = new TermQuery(new Term("content","int")); TermQuery termQuery2 = new TermQuery(new Term("content","nikos"));BooleanQuery booleanQuery = new BooleanQuery();booleanQuery.add(termQuery,BooleanClause.Occur.SHOULD); booleanQuery.add(termQuery2,BooleanClause.Occur.SHOULD);TopDocs topDocs =searcher.search(booleanQuery, maxHits);這雖然不太困難,但是創(chuàng)建更復(fù)雜的析取查詢有點棘手。 如何正確使用它并不總是那么簡單。
例如,讓我們嘗試查找所有包含單詞“ nikos”和短語“ httpservletresponse response”或單詞“ int”的文檔。 一個人可以這樣寫:
TermQuery termQuery = new TermQuery(new Term("content","nikos"));PhraseQuery phraseQuery = new PhraseQuery(); phraseQuery.add(new Term("content","httpservletresponse")); phraseQuery.add(new Term("content","response"));BooleanQuery booleanQuery = new BooleanQuery();booleanQuery.add(phraseQuery,BooleanClause.Occur.MUST); booleanQuery.add(termQuery,BooleanClause.Occur.MUST); booleanQuery.add(new TermQuery(new Term("content","int")),BooleanClause.Occur.SHOULD);TopDocs topDocs =searcher.search(booleanQuery, maxHits);但是查詢將無法提供所需的結(jié)果。 請記住,如我們所構(gòu)造的那樣,此查詢的結(jié)果必須同時包含單詞"nikos"并且必須同時包含短語"httpservletresponse response" 。 但這不是您想要的。 您需要包含nikos單詞和短語"httpservletresponse response"文檔,但也希望獨立包含單詞"int"文檔,無論它們是否包含其他子句。 公平地說,上述布爾查詢有點錯誤。 因為用直接的布爾語法,您永遠都不會這樣寫:A AND B ORC。您應(yīng)該寫(A AND B)ORC。或者A AND(B OR C)。 看到不同?
因此,您應(yīng)該編寫所需的查詢:(“ nikos”和“ httpservletresponse response”)或“ int”。
您可以將BooleanQueries組合在一起。 使用上面嚴(yán)格的語法,很難想象這將如何進行:
TermQuery termQuery = new TermQuery(new Term("content","nikos"));PhraseQuery phraseQuery = new PhraseQuery(); phraseQuery.add(new Term("content","httpservletresponse")); phraseQuery.add(new Term("content","response"));// (A AND B) BooleanQuery conjunctiveQuery = new BooleanQuery(); conjunctiveQuery.add(termQuery,BooleanClause.Occur.MUST); conjunctiveQuery.add(phraseQuery,BooleanClause.Occur.MUST);BooleanQuery disjunctiveQuery = new BooleanQuery();// (A AND B) OR C disjunctiveQuery.add(conjunctiveQuery,BooleanClause.Occur.SHOULD); disjunctiveQuery.add(new TermQuery(new Term("content","int")),BooleanClause.Occur.SHOULD);TopDocs topDocs =searcher.search(disjunctiveQuery, maxHits);這是使用BooleanQuery類構(gòu)造布爾查詢時可以遵循的快速指南:
- X和Y
- X或Y
- BooleanQuery bool = new BooleanQuery(); bool.add(X,BooleanClause.Occur.SHOULD); bool.add(Y,BooleanClause.Occur.SHOULD);
- X AND(不是Y)
- BooleanQuery bool = new BooleanQuery(); bool.add(X,BooleanClause.Occur.MUST); bool.add(Y,BooleanClause.Occur.MUST_NOT);
- (X和Y)或Z
- BooleanQuery conj = new BooleanQuery();conj.add(X,BooleanClause.Occur.MUST); conj.add(Y,BooleanClause.Occur.MUST);BooleanQuery disj = new BooleanQuery(); disj.add(conj,BooleanClause.Occur.SHOULD) disj.add(Z,BooleanClause.Occur.SHOULD)
- (X或Y)和Z
- BooleanQuery conj = new BooleanQuery();conj.add(X,BooleanClause.Occur.SHOULD); conj.add(Y,BooleanClause.Occur.SHOULD);BooleanQuery disj = new BooleanQuery(); disj.add(conj,BooleanClause.Occur.MUST) disj.add(Z,BooleanClause.Occur.MUST)
- X或(非Z)
- BooleanQuery neg = new BooleanQuery();neg.add(Z,BooleanClause.Occur.MUST_OT);BooleanQuery disj = new BooleanQuery();
disj.add(neg,BooleanClause.Occur.SHOULD)
disj.add(X,BooleanClause.Occur.SHOULD)
上面的代碼可用于創(chuàng)建越來越復(fù)雜的布爾查詢。
2.4通配符查詢
顧名思義,您可以使用WildcardQuery類使用“ *”或“?”執(zhí)行通配符查詢。 字符。 例如,如果要o搜索包含以'ni'開頭的詞條,然后是其他任何字符序列的文檔,則可以搜索'ni *'。 如果要搜索以“ jamie”開頭(后接(任意)一個字符)的術(shù)語,則可以搜索“ jamie?”。 就那么簡單。 自然地, WildcardQueries效率低下,因為搜索可能要經(jīng)過很多不同的術(shù)語才能找到匹配項。 通常,最好避免將通配符放在單詞的開頭,例如“ * abcde”。
讓我們來看一個例子:
Query wildcardQuery = new WildcardQuery(new Term("content","n*os")); TopDocs topDocs =searcher.search(wildcardQuery, maxHits);和
Query wildcardQuery = new WildcardQuery(new Term("content","niko?")); TopDocs topDocs =searcher.search(wildcardQuery, maxHits);2.5 RegexpQuery
使用RegexpQuery ,您可以執(zhí)行快速的正則表達式查詢,并通過Lucene的快速自動機實現(xiàn)對其進行評估。 這是一個例子
Query regexpQuery = new RegexpQuery(new Term("content","n[a-z]+"));TopDocs topDocs =searcher.search(regexpQuery, maxHits);2.6 TermRangeQuery
當(dāng)對字符串術(shù)語執(zhí)行范圍查詢時,此查詢子類很有用。 例如,您可以搜索“ abc”和“ xyz”兩個詞之間的字詞。 字的比較是使用Byte.compareTo(Byte)執(zhí)行的。 您可能會發(fā)現(xiàn)這對于在文檔元數(shù)據(jù)中進行范圍查詢(例如標(biāo)題甚至日期)特別有用(如果使用日期,請小心使用DateTools )。
以下是查找上周創(chuàng)建的所有文檔的方法:
Calendar c = Calendar.getInstance(); c.add(Calendar.DATE, -7); Date lastWeek = c.getTime();Query termRangeQuery = TermRangeQuery.newStringRange("date", DateTools.dateToString(new Date(), DateTools.Resolution.DAY),DateTools.dateToString(lastWeek, DateTools.Resolution.DAY),true,true);當(dāng)然,在為“日期”字段建立索引時必須小心。 您還必須將DateTools.dateToString應(yīng)用于它,并指定不進行分析的字段(這樣就不會標(biāo)記化該字段并將其拆分為單詞)。
2.7 NumberRangeQuery
這用于執(zhí)行數(shù)字范圍查詢。 想象一下,您有一個“ wordcount”字段,用于存儲該文檔的單詞數(shù),并且您要檢索的單詞數(shù)在2000到10000之間:
Query numericRangeQuery = NumericRangeQuery.newIntRange("wordcount",2000,10000,true,true);布爾參數(shù)指示范圍內(nèi)包括上限和下限。
2.8模糊查詢
這是一個非常有趣的查詢子類。 該查詢根據(jù)鄰近度量(例如眾所周知的Damerau-Levenshtein距離)評估字詞。 這將找到詞典順序接近的單詞。 如果您想執(zhí)行復(fù)雜的詞典應(yīng)用程序,例如詞典或“您要說的話”字詞建議功能,則可以使用SpellChecker API 。
讓我們看看如何執(zhí)行不幸的“字符串”拼寫錯誤的模糊查詢搜索:
Query fuzzyQuery = new FuzzyQuery(new Term("content","srng"));翻譯自: https://www.javacodegeeks.com/2015/09/lucene-query-search-syntax-examples.html
lucene 查詢示例
總結(jié)
以上是生活随笔為你收集整理的lucene 查询示例_Lucene查询(搜索)语法示例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 研发项目科技局备案(集团科研备案)
- 下一篇: 建立索引lucene_用Lucene建立