用户在搜索引擎中进行搜索时,常常查找的并非是一个简单的单词,很有可能是几个不同的关键字。这些关键字之间要么是紧密相联,成为一个精确的短 语,要么是可能在这几个关键字之间还插有其他无关的关键字。此时,用户希望将它们找出来。不过很显然,从评分的角度看,这些关键字之间拥有与查找内容无关 短语所在的文档的分值一般会较低一些。
PhraseQuery正是Lucene所提供的满足上述需求的一种Query对象。它的add方法可以让用户往其内部添加关键字,在添加完毕后,用户还可以通过setSlop()方法来设定一个称之为“坡度”的变量来确定关键字之间是否允许、允许多少个无关词汇的存在。
package ch11; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.PhraseQuery; import org.apache.lucene.search.PrefixQuery; public class PhraseQueryTest { public static void main(String[] args) throws Exception { //生成Document对象 Document doc1 = new Document(); //添加“content”字段的内容 doc1.add(Field.Text("content", "david mary smith robert")); //添加“title”字段的内容 doc1.add(Field.Keyword("title", "doc1")); //生成索引书写器 IndexWriter writer = new IndexWriter("c://index", new StandardAnalyzer(), true); //设置为混合索引格式 writer.setUseCompoundFile(true); //将文档添加到索引中 writer.addDocument(doc1); //关闭索引 writer.close(); //生成索引搜索器 IndexSearcher searcher = new IndexSearcher("c://index"); //构造词条 Term word1 = new Term("content", "david"); Term word2 = new Term("content","mary"); Term word3 = new Term("content","smith"); Term word4 = new Term("content","robert"); //用于保存检索结果 Hits hits = null; //生成PhraseQuery对象,初始化为null PhraseQuery query = null; // 第一种情况,两个词本身紧密相连,先设置坡度为0,再设置坡度为2 query = new PhraseQuery(); query.add(word1); query.add(word2); //设置坡度 query.setSlop(0); //开始检索,并返回检索结果 hits = searcher.search(query); //输出检索结果的相关信息 printResult(hits, "'david'与'mary'紧紧相隔的Document"); //再次设置坡度 query.setSlop(2); //开始第二次检索 hits = searcher.search(query); //输出检索结果 printResult(hits, "'david'与'mary'中相隔两个词的短语"); // 第二种情况,两个词本身相隔两个词,先设置坡度为0,再设置坡度为2 query = new PhraseQuery(); query.add(word1); query.add(word4); //设置坡度 query.setSlop(0); //开始第三次检索,并返回检索结果 hits = searcher.search(query); //输出检索结果 printResult(hits, "'david'与'robert'紧紧相隔的Document"); //设置坡度 query.setSlop(2); //开始第四次检索,并返回检索结果 hits = searcher.search(query); //输出检索结果 printResult(hits, "'david'与'robert'中相隔两个词的短语"); } public static void printResult(Hits hits, String key) throws Exception {System.out.println("查找 /"" + key + "/" :"); if (hits != null) { if (hits.length() == 0) { System.out.println("没有找到任何结果"); System.out.println(); } else { System.out.print("找到"); for (int i = 0; i < hits.length(); i++) { //取得文档对象 Document d = hits.doc(i); //取得“title”字段的内容 String dname = d.get("title"); //输出相关的信息 System.out.print(dname + " "); } System.out.println(); System.out.println(); } } } }
在上述代码中创建了一个Document,这个Document的“content”域中含有4个关键字。接下来,代码创建了一个PhraseQuery对象,首先将前两个紧紧相连关键字放入其中,并设置它们的坡度值分别为0和2,接下来,又将第一个和最后一个关键字放入其中,同样设置它们的坡度值为0和2。