package lucene;

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;

/**
 * @author 赵学庆 www.java2000.net
 * @author 作者: 李刚 宋伟 邱哲 出处:人民邮电出版社
 */
public class PhraseQueryTest {
  public static void main(String[] args) throws Exception {
    // 生成Document对象
    Document doc1 = new Document();
    // 添加"content"字段的内容
    doc1.add(new Field("content", "david mary smith robert", Field.Store.YES, Field.Index.TOKENIZED));
    // 添加"title"字段的内容
    doc1.add(new Field("title", "doc1", Field.Store.YES, Field.Index.TOKENIZED));
    // 生成索引书写器
    IndexWriter writer = new IndexWriter("d:\\index\\testPhrase", new StandardAnalyzer(), true);
    // 设置为混合索引格式
    writer.setUseCompoundFile(true);
    // 将文档添加到索引中
    writer.addDocument(doc1);
    // 关闭索引
    writer.close();
    // 生成索引搜索器
    IndexSearcher searcher = new IndexSearcher("d:\\index\\testPhrase");
    // 构造词条
    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();
      }
    }
  }
}


运行结果
引用:
查找 "'david'与'mary'紧紧相隔的Document" :
找到doc1

查找 "'david'与'mary'中相隔两个词的短语" :
找到doc1

查找 "'david'与'robert'紧紧相隔的Document" :
没有找到任何结果

查找 "'david'与'robert'中相隔两个词的短语" :
找到doc1


总结:
对两个紧连的关键字来说无论将坡度设置为多少,Lucene总能找到它所在的文档,而对两个不紧连的关键字,如果坡度值小于它们之间无关词的数量,那么则无法找到。其实,当两个关键字之间的无关词数小于等于坡度值时,总是可以被找到。
快乐渡过每一天,减肥坚持每一天