全文检索技术_Lucene搜索
本文回顾了《全文检索技术专栏》系列文章中涉及倒排索引算法原理、Lucene分词机制以及索引构建过程的技术要点。研究发现,在信息处理领域中, Lucene系统以其卓越的知识组织与检索能力而闻名, 其核心优势在于非搜索引擎这一独特功能。该系统支持诸如词项匹配查询、跨域复合查询、布尔逻辑组合查询等多种检索方式, 在实际应用中展现出强大的信息处理能力。具体而言, 在执行检索操作时, 将用户需求条件封装为一个Query对象, 并最终返回一组符合条件的Document数据。
词项查询
在信息检索系统中,词项查询是一种基础且常见的操作方式,在数据库设计中被广泛应用。具体而言,在一个给定的领域内(即一个特定的数据库表中),通过输入相关的关键词来进行数据检索是词项查询的基本功能。系统会首先检查倒排索引表中的相关条目是否存在,在确认无误后会将所有满足条件的文档集合进行返回。
      @Test
    public void termQuery() throws IOException {
        //指定一个文件输出目录
        Path path= Paths.get("d:/test/index");
        //将路径交给FSDirectory完成路径的管理,当路径不存在时,由FSDirectory帮你创建
        FSDirectory fsDirectory=FSDirectory.open(path);
    
        //创建索引输入流
        IndexReader indexReader= DirectoryReader.open(fsDirectory);
        IndexSearcher indexSearcher=new IndexSearcher(indexReader);
        
        //创建词项查询条件
        Term term=new Term("title","巴西");
        Query query= new TermQuery(term);
    
        //查询
        TopDocs docs = indexSearcher.search(query, 3);
        ScoreDoc[] scoreDocs=docs.scoreDocs;
        for (ScoreDoc scoreDoc:scoreDocs){
            //获取document对象属性
            //documentId
            int did = scoreDoc.doc;
            Document docObj = indexSearcher.doc(did);
            System.out.println("============"+did+"============");
            System.out.println(docObj.get("title"));
            System.out.println(docObj.get("origin"));
            System.out.println(docObj.get("content"));
    
        }
    }
        查询结果:

多域查询
在上述的词汇检索操作中,在当前系统中我们仅限于检索标题信息。若希望同时涵盖标题、来源和内容等关键词的检索需求,则应当采用多源领域查询方法。
程序代码和词项查询之间的差异不大,主要区别在于如何构建查询条件与构建查询对象的方法存在差异:
     @Test
    public void multiQuery() throws IOException, ParseException {
        //指定一个文件输出目录
        Path path= Paths.get("d:/test/index");
        //将路径交给FSDirectory完成路径的管理,当路径不存在时,由FSDirectory帮你创建
        FSDirectory fsDirectory=FSDirectory.open(path);
        
        //创建索引输入流
        IndexReader indexReader= DirectoryReader.open(fsDirectory);
        IndexSearcher indexSearcher=new IndexSearcher(indexReader);
        
        //要查询的域
        String[] files={"title","origin","content"};
        //创建多域查询条件
        MultiFieldQueryParser parser=new MultiFieldQueryParser(files,new SmartChineseAnalyzer());
        Query query= parser.parse("巴西");
        //查询
        TopDocs docs = indexSearcher.search(query, 3);
        ScoreDoc[] scoreDocs=docs.scoreDocs;
        for (ScoreDoc scoreDoc:scoreDocs){
            //获取document对象属性
            //documentId
            int did = scoreDoc.doc;
            Document docObj = indexSearcher.doc(did);
            System.out.println("============"+did+"============");
            System.out.println(docObj.get("title"));
            System.out.println(docObj.get("origin"));
            System.out.println(docObj.get("content"));
            
        }
    }
        查询结果:

布尔查询
布尔查询是最常用且广泛应用的一种查询方法。它能够整合所有其他相关查询参数,并通过灵活的方式进行组合设置以满足复杂需求。任何query对象都可以作为布尔逻辑的一部分来应用,并根据具体需求进行优化配置以获得理想结果。例如,在京东平台购买智能手机时,用户可以选择品牌型号、价格区间以及存储容量等多种参数进行精准筛选与匹配查找功能的调用
由于前后代码都类似,这里只展示查询条件的创建过程:
     //要查询的域
      String[] files={"title","origin","content"};
    //创建多域查询条件1
    MultiFieldQueryParser parser=new MultiFieldQueryParser(files,new SmartChineseAnalyzer());
    Query query= parser.parse("疫苗");
    //创建词项查询条件2
    Term term=new Term("title","中国");
    Query query2= new TermQuery(term);
    
    //封装布尔查询子条件
    BooleanClause bc1=new BooleanClause(query,BooleanClause.Occur.MUST);
    BooleanClause bc2=new BooleanClause(query2,BooleanClause.Occur.MUST);
    
    //封装最终查询条件
    Query finalQuery=new BooleanQuery.Builder().add(bc1).add(bc2).build();
        在代码中,请注意以下这两项的意思是这些查询都涉及相同的查询内容,并且它们都匹配了相同的关键词汇和主题信息。
生成一个名为bc1的实例:
BooleanClause bc1 = new BooleanClause(query, BooleanClaue Occur.MUST);
同样地,
生成一个名为bc2的实例:
BooleanClause bc2 = new BooleanClaue(query2, BooleanClaue Occur.MUST);
这里的各种组合关系,我们用图例说明:
取得query和query2查询子句的交集:

表示查询结果中不能包含MUST_NOT所对应的查询子句的检索结果:

MUST_NOT和MUST_NOT连用,没有任何搜索结果,查询无意义:

除此之外,还有SHOULD,有兴趣的可以继续深入拓展。
范围查询
该系统支持针对域属性中的数字类型的范围查询操作。例如,在数据库中可以执行如下操作:根据文章的点击率字段筛选出值落在10至70之间的文章记录。
     //范围查询 文章点击率在10-70次的文档
     Query rangeQuery=IntPoint.newRangeQuery("clickNum",10,70);
        模糊查询
在title域中查找和“苗”类似的词语:
    //模糊查询
    Query fuzzyQuery=new FuzzyQuery(new Term("title","苗"));
        通配查询
?代表任意一个字符。* 代表任意多个字符。
     //通配查询
    Query wquery=new WildcardQuery(new Term("content","?国"));
        