Lucene笔记10-Lucene的搜索-其他常用Query搜索

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36059561/article/details/83218591

一、前缀搜索

// 前缀查询
public void searchByPrefix(String field, String name, int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        Query query = new PrefixQuery(new Term(field, name));
        TopDocs topDocs = indexSearcher.search(query, number);
        System.out.println("一共查询到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

二、通配符搜索

// 通配符查询
public void searchByWildcard(String field, String name, int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        // 在传入的name中可以使用通配符,有?和*两种,?表示匹配一个字符,*表示匹配任意多个字符
        Query query = new WildcardQuery(new Term(field, name));
        TopDocs topDocs = indexSearcher.search(query, number);
        System.out.println("一共查询到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

三、布尔查询

可以使用布尔查询来组合查询,使用MUST、SHOULD、MUST_NOT把要筛选的情况构造出来即可。

// 布尔查询
public void searchByBoolean(int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        BooleanQuery booleanQuery = new BooleanQuery();
        // MUST:必须出现;SHOULD:可以出现也可以不出现;MUST_NOT:不能出现
        booleanQuery.add(new TermQuery(new Term("name", "lisi")), BooleanClause.Occur.MUST);
        booleanQuery.add(new TermQuery(new Term("content", "content")), BooleanClause.Occur.SHOULD);
        booleanQuery.add(new TermQuery(new Term("email", "[email protected]")), BooleanClause.Occur.MUST_NOT);
        TopDocs topDocs = indexSearcher.search(booleanQuery, number);
        System.out.println("一共查询到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

四、短语查询

关于这里的setSlop(),多说两句,slop是移动距离的意思,假如要查询的内容是I like football,首先setSlop(1),再去add对content域查询i和对content域查询football,可以查询出来,如果我将i和football的add顺序颠倒一下,再次查询,会发现没有结果,此时,如果我将setSlop()的参数改为3,再去查询,就会查到刚刚的数据,这是为什么呢?

因为这个slop不是单纯的指单词间距,而是移动距离,对于添加顺序是football i的情况,football右移1位,football和i重叠,右移2位,变成i football,右移3位,变成i * football,此时正好可以匹配上i like football。所以说setSlop()为3反而能查到是这个原因。如果我们setSlop(4)呢?经过查询发现也能查到,也就是说我们set的这个slop是一个最大值,小于等于当前值的也包括在内。

另外,这个查询需要对字符进行移动,对性能有一定的影响,所以要尽量使用。

最后一点,这个查询不支持中文,因为查询中的短语间距分词是以空格作为标志的,所以只能适用于英文查询。

// 短语查询
public void searchByPhrase(int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        PhraseQuery phraseQuery = new PhraseQuery();
        // 设置短语距离
        phraseQuery.setSlop(1);
        // 原文是“I like football”,但是这里的I会被转化为小写,所以查询的时候也是使用小写
        phraseQuery.add(new Term("content","i"));
        phraseQuery.add(new Term("content","football"));
        TopDocs topDocs = indexSearcher.search(phraseQuery, number);
        System.out.println("一共查询到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

五、模糊查询

我们需要查询lisi,但是我们输入的是lixi,发现也可以查询出来,这就是模糊查询,它允许我们错误输入某些字符,但是当我们改为bixi,发现就查不到了,说明模糊查询允许我们输入错误一个字符。我们可以通过构造函数来修改这个相似程度。简单了解下即可,对中文的支持也不好。

// 模糊查询
public void searchByFuzzy(int number) {
    IndexSearcher indexSearcher = getIndexSearcher();
    try {
        // FuzzyQuery(Term term, float minimumSimilarity, int prefixLength, int maxExpansions)
        // minimumSimilarity是最小相似度,取值范围为0.0~1.0,包含0.0但不包含1.0,默认值为0.5
        // 当这个值越小,通过模糊查找出的文档的匹配程度就越低,文档的数量也就越多;当这个值越大,说明要匹配程度更大,匹配的文档数也就越少
        // 当相似度设置为1,那么就退化为TermQuery查询,所以当这个值>=1或<0会抛出IllegalArgumentException异常
        // prefixLength是前缀长度,默认为0,表示在进行模糊匹配的时候,要有多少个前缀字母必须完全匹配
        Query query = new FuzzyQuery(new Term("name", "lixi"));
        TopDocs topDocs = indexSearcher.search(query, number);
        System.out.println("一共查询到:" + topDocs.totalHits);
        for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
            Document document = indexSearcher.doc(scoreDoc.doc);
            System.out.println(document.get("id") + " " + document.get("name") + " " + document.get("email"));
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexSearcher != null) {
            try {
                indexSearcher.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_36059561/article/details/83218591