上QQ阅读APP看书,第一时间看更新
3.3.6 短语查询
如果按字索引中文文档,则查询的时候往往要求文档中的这些字是连续出现的。使用PhraseQuery可以查询连续出现的几个关键词。PhraseQuery称为短语匹配查询,用于要求精确匹配的查询。PhraseQuery使用了词保存在索引中的位置信息,因此需要索引中的相关列已经保存了位置信息。例如按字索引,按字查询“开封”:
PhraseQuery query = new PhraseQuery(); query.add(new Term("subject", "开")); query.add(new Term("subject", "封"));
搜索“软件工程师”时,标题为“安卓软件开发工程师”排第一位,而标题为“软件工程师”反而排在后面。词库为:“软件”“工程师”。为了解决这个问题,可以增加短语查询:
PhraseQuery query = new PhraseQuery(); query.add(new Term("subject", "软件")); query.add(new Term("subject", "工程师"));
有时候要匹配上的词之间有间隔,匹配上的词之间的距离称为slop。默认情况下,slop的值是0,可以通过调用setSlop()方法设置这个值。例如,用户搜索“西红柿牛腩”时,会匹配上“西红柿炖牛腩”。
PhraseQuery query = new PhraseQuery(); query.setSlop(1); query.add(new Term("subject", "西红柿")); query.add(new Term("subject", "牛腩"));
使用PhraseQuery完整的例子:
public static void main(String[] args) throws Exception { //在内存中建立索引 Directory directory = new RAMDirectory(); Analyzer analyzer = new StandardAnalyzer(); IndexWriterConfig iwc = new IndexWriterConfig(analyzer); IndexWriter writer = new IndexWriter(directory, iwc); // 索引一些文档 writer.addDocument(createDocument("1", "foo bar baz")); writer.addDocument(createDocument("2", "red green blue")); writer.addDocument(createDocument("3", "test foo bar test")); writer.close(); // 查找包含foo bar这个短语的文档 String sentence = "foo bar"; IndexReader reader = IndexReader.open(directory); // 根据IndexReader创建IndexSearcher IndexSearcher searcher = new IndexSearcher(reader); PhraseQuery query = new PhraseQuery(); String[] words = sentence.split(" "); for (String word : words) { query.add(new Term("contents", word)); } // 显示搜索结果 TopDocs topDocs = searcher.search(query, 10); for (ScoreDoc scoreDoc : topDocs.scoreDocs) { Document doc = searcher.doc(scoreDoc.doc); System.out.println(doc); } } private static Document createDocument(String id, String content) { Document doc = new Document(); doc.add(new Field("id", id, Store.YES, Index.NOT_ANALYZED)); doc.add(new Field("contents", content, Store.YES, Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); return doc; }