搜索引擎Lucene(5):搜索执行过程及搜索类型

1、搜索处理示例

public class Searcher {
    public static void search(String indexDir, String q) throws IOException, ParseException {
        // 得到读取索引文件的路径
        Directory dir = FSDirectory.open(Paths.get(indexDir));
        // 通过Dir得到路径下所有文件
        IndexReader reader = DirectoryReader.open(dir);
        // 建立索引查询器
        IndexSearcher searcher = new IndexSearcher(reader);
        // 实例化分析器
        Analyzer analyzer = new StandardAnalyzer();
        /********建立查询解析器********/
        // 第一个参数是要查询的字段; 第二个参数市分析器Analyzer
        String[] fields = {"name", "path"};
        Map<String, Float> fieldMap = new HashMap<>();
        fieldMap.put("name",100.0f);
        fieldMap.put("path",1.0f);
        QueryParser parser = new MultiFieldQueryParser(fields,new CJKAnalyzer());
        // 根据传进来的q查找
        Query query = parser.parse(q);
        // 计算索引开始时间
        long start = System.currentTimeMillis();
        /********开始查询********/
        // 第一个参数是通过传过来的参数来查找得到的query; 第二个参数是要查询出的行数
        TopDocs hits = searcher.search(query,10);
        // 计算索引结束时间
        long end = System.currentTimeMillis();
        System.out.println("匹配 "+ q + ",查询到 " + hits.totalHits + " 个记录, 用时:" + (end - start));

        // 遍历hits.scoreDocs,得到scoreDoc
        // scoreDoc:得分文档,即得到的文档  scoreDocs:代表topDocs这个文档数组
        for (ScoreDoc scoreDoc : hits.scoreDocs) {
            Document doc = searcher.doc(scoreDoc.doc);
            System.out.println("name:" + doc.get("name") + " ,path=" + doc.get("path"));
        }
        //关闭reader
        reader.close();
    }
}

2、搜索类型

在lucene中,查询就是构建Query对象。搜索文档时会实例化一个IndexSearcher对象,IndexSearcher对象的search()方法完成搜索过程,Query对象作为search()方法的对象。搜索结果会保存在一个TopDoc类型的文档集合中,遍历TopDocs集合输出文档信息。

2.1、多域搜索(MultiFieldQueryParser)

MultiFieldQueryParser可以查询多个字段。示例如下:

String[] fields = {"title","content"};
Analyzer analyzer = new IKAnalyzer6X(true);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,analyzer);
Query q = parser.parse("日本");

2.2、词项搜索(TermQuery)

TermQuery是最简单也是最常用的Query。在搜索引擎中最基本的搜索就是在索引中搜索某一词条,而TermQuery就是用来完成这项工作的。示例代码:

Term term = new Term("title","美国");
Query q = new TermQuery(term);

2.3、布尔搜索(BooleanQuery)

BooleanQuery是常用的查询,其实际是一个组合查询,在使用时可以把各种Query对象添加进去并标明他们之间的逻辑关系。BooleanQuery本身是一个布尔子句的容积,其专门提供了api方法想其中添加子句,并标明他们之间的关系。代码示例:

Query q1 = new TermQuery(new Term("title","中国"));
Query q2 = new TermQuery(new Term("content","北京"));
BooleanClause bc1 = new BooleanClause(q1, Occur.MUST);
BooleanClause bc2 = new BooleanClause(q2, Occur.MUST_NOT);
BooleanQuery bq = new BooleanQuery.Builder().add(bc1).add(bc2).build();

2.4、范围搜索(RangeQuery )

RangeQuery可以查询满足一定范围的文档,如某段时间的所有文档等。RangeQuery表示在某范围内查询的条件,实现从一个开始词条到一个结束词条的搜索功能。示例如下:

Query rq = IntPoint.newRangeQuery("relay",1000,2000);

2.5、前缀搜索(PrefixQuery)

PrefixQuery就是使用前缀来进行查找的。通常先定义一个词条Term。该词条包含查找的字段名及关键字前缀,然后通过该词条构造一个PrefixQuery对象,就可以进行前缀查询了。示例如下:

Term t = new Term("title","你好");
Query pq = new PrefixQuery(term);

2.6、多关键字搜索(PhraseQuery)

用户搜索时,可能会输入几个不同的关键词,这些关键词要么紧密相连,构成一个精确的短语,要么直接插入其他无关内容。而hraseQuery正可以满足多关键词的查询,其通过add()方法可以向用户添加多个关键字,同时还可通过setSlop()设定坡度变量来确定是否允许或允许多少无关的词汇存在。示例代码:

PhraseQuery.Builder builder = new PhraseQuery.Builder();
builder.add(new Term("title","中国"),2);
builder.add(new Term("title","美国"),3);
PhraseQuery pq = builder.build();

2.7、模糊搜索(FuzzyQuery)

FuzzyQuery是一种模糊搜索,其可以简单识别两个相近的词语。如将“Trump”拼写错误为“tramp”,使用FuzzyQuery可以得到正确的结果。示例如下:

Term t = new Term("title","tramp");
FuzzyQuery fq = new FuzzyQuery(t);

2.8、通配符搜索(WildcardQuery)

WildcardQuery为通配符查询,代码示例:

WildcardQuery wq = new WildcardQuery(new Term("title","学?"));

3、搜索过滤

过滤器是用于缩小搜索空间的一种机制,它把可能的搜索匹配结果仅限制在所有文档的一个子集中。他们可以用来对得到的搜索匹配结果进行进一步的搜索,以实现在搜索结果中继续搜索的特性。此外,它们还可以用来限制文档的搜索空间。安全过滤允许用户只能看到属于自己的文档搜索结果,即时这些查询实际上还是匹配上了其他文档。

TermRangeFilter:只对包含特定项范围的文档进行匹配操作。功能与TermRangeQuery一致,但没有评分操作。TermRangeFilter的处理对象是文本域,如果为数字,需使用NumericRangeFilter。
NumericRangeFilter:复制过滤数值范围的文档。其功能与去除评分功能的NumericRangeQuery类一致;
FieldCacheRangeFilter:提供了另一种范围的过滤选择。它所完成的过滤功能同TermRangeFilter和NumericRangeFilter加起来一样,但它使用的却是基于lucene的域缓存机制。其可以在某些情况下带来系统性能提升。
QueryWrapperFilter:使用查询中匹配的文档来对随后搜索中可以访问的文档进行限制。它允许你将带有评分功能的查询转换为不带评分功能的过滤器。使用QueryWrapperFilter可以将被搜索文档限制在特定的类别范围内。
SpanQueryFilter:SpanQueryFilter完成与QueryWrapperFilter一样的功能,区别是前者能够保留针对每个匹配文档的跨度。
PerfixFilter:其是PrefixQuery的必然结果,它会对包含以特定前缀开始的项的文档进行匹配。我们可以用PrefixFilter来讲搜索范围限制在某个指定类别的所有书籍中。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,425评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,058评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,186评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,848评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,249评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,554评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,830评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,536评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,239评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,505评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,004评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,346评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,999评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,060评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,821评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,574评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,480评论 2 267

推荐阅读更多精彩内容