Lucene 9.x Query 查询器使用

编程教程 > Java (9) 2025-04-30 10:24:06

项目环境

maven 项目

   <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <lucene.version>9.12.1</lucene.version>
        <hutool.all.version>5.8.26</hutool.all.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- Lucene Search engines must -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <!--9.x renamed analyzers to analysis-->
            <artifactId>lucene-analysis-common</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queries</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-highlighter</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>${lucene.version}</version>
        </dependency>

        <!-- Chinese word segmentation dependence -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <!--9.x renamed analyzers to analysis-->
            <artifactId> lucene-analysis-smartcn</artifactId>
            <version>${lucene.version}</version>
        </dependency>
        <dependency>
            <groupId>com.github.magese</groupId>
            <artifactId>ik-analyzer</artifactId>
            <version>8.5.0</version>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>${hutool.all.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.38</version>
        </dependency>

    </dependencies>

JDK 版本

jdk 17

 

示例公用源码部分

抽离公用部分源码方便展示

结果展示统一使用

    public static void showSearchResults(IndexSearcher indexSearcher, ScoreDoc[] hits) throws IOException {
        System.out.println("------------------------结果呈现 START------------------------------");
        System.out.printf("找到 %s 个结果%n", hits.length);
        for (ScoreDoc scoreDoc : hits) {
            int docId = scoreDoc.doc;
            float score = scoreDoc.score;
            Document document = indexSearcher.doc(docId);
            StringBuffer sb = new StringBuffer();
            document.getFields().forEach(field -> {
                String name = field.name();
                String value = field.stringValue();
                sb.append(name).append("=").append(value).append(" , ");
            });
            System.out.printf(sb+"score: %s%n", score);
        }
        System.out.println("------------------------结果呈现 END------------------------------");
    }

添加模拟数据使用

    public static void addDocument(IndexWriter indexWriter,String name,Long price,String sn)throws IOException{
        Document doc = new Document();
        doc.add(new TextField("name", name, Field.Store.YES));
        doc.add(new LongPoint("price", price));
        doc.add(new StoredField("price", price));
        doc.add(new StringField("sn", sn, Field.Store.YES));
        indexWriter.addDocument(doc);
    }

索引存放目录

static String path="src/main/resources/index/app3";

QueryParser 简单查询/万能查

支持字段类型

StringField TextField

查询示例

   public static void main(String[] args) throws IOException, org.apache.lucene.queryparser.classic.ParseException {
        //索引存放目录
        try (FSDirectory directory = FSDirectory.open(Paths.get(path));
             //分词器
             Analyzer analyzer = new SmartChineseAnalyzer();
             IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(analyzer));
        ){
            //创建索引
            addDocument(indexWriter,"风冷变频节能空调小米1PRO",1999L,"XIAOMI-1PRO");
            addDocument(indexWriter,"变频节能好空调美的X1",2999L,"Media-X1");
            addDocument(indexWriter,"变频节能风管机空调小米G1Pro",3999L,"XIAOMI-G1PRO");
            addDocument(indexWriter,"变频节能风扇小米F001",299L,"XIAOMI-F001");
            addDocument(indexWriter,"变频节能风扇美的FX01",399L,"Media-FX01");
            //提交索引写到文件
            indexWriter.commit();

            IndexSearcher indexSearcher = new IndexSearcher(DirectoryReader.open(directory));


            //查询
            Query query =  new QueryParser("name",analyzer).parse("风冷空调");


            TopDocs topDocs_10 = indexSearcher.search(query, 10);
            ScoreDoc[] scoreDocArray = topDocs_10.scoreDocs;
            showSearchResults(indexSearcher,scoreDocArray);

            //测试索引删除
            indexWriter.deleteAll();
        }
    }

查询结果:

Lucene 9.x Query 查询器使用_图示-6869ae3c9c3b42dd80780c03f8a27f7a.png

修改查询词

Query query =  new QueryParser("name",analyzer).parse("变频风扇");

查询结果

Lucene 9.x Query 查询器使用_图示-9df1884aa7c14d909e344b81d04d3d70.png

PrefixQuery 前缀查询器

支持字段类型

StringField TextField

前缀查询器查询分词示例

Query query =  new PrefixQuery(new Term("name","变频"));

查询结果

Lucene 9.x Query 查询器使用_图示-04db4a4b8d2a4d569e9c99fbf5abcc07.png

是不是感觉和平时的前缀查询结果不一致。是因为PrefixQuery查询器,查询的字段是参与分词的,所以的前缀是相对于分词后的词匹配的,并非分词前数据

查询不分词的字段示例

sn试试

 Query query =  new PrefixQuery(new Term("sn","Media"));

查询结果:

Lucene 9.x Query 查询器使用_图示-0ff91e3c8b1741beb4d57743a4fdc65e.png

由于没分词,所以结果和普通的前缀查询一样。

 

WildcardQuery 通配符查询器

支持字段类型

StringField TextField

示例

Query query =  new WildcardQuery(new Term("sn","XIAOMI*"));

查询结果

Lucene 9.x Query 查询器使用_图示-1e049416ab4a4daa9a75f8eea166734b.png

提示:查询分词字段,则匹配的是分词后的词语,与上方前缀查询逻辑一致

 

TermQuery 精确查询

支持字段类型

StringField TextField

代码示例

Query query =  new TermQuery(new Term("name","风扇"));

执行结果:

Lucene 9.x Query 查询器使用_图示-a53bc76dfe0e44c6b4d54d95ed30479b.png

提示:这里的精确查询是指存的索引词精确,由于上面两个通过分词器存入索引时候分出来了风扇词语,所以能精确匹配。另外可与StringField配合实现 ID搜索功能

 

数字范围查询

支持字段类型

  • FloatField  
  • DoubleField
  • IntField
  • LongField
  • FloatPoint  
  • DoublePoint
  • IntPoint
  • LongPoint

示例

Query query = LongPoint.newRangeQuery("price", 2000, 5000);

执行结果示例:

Lucene 9.x Query 查询器使用_图示-29c8a14c39ae41cfb49615d9ad1f361f.png

提示:前面字段用啥类型存放的这里用啥类型创建查询器,注意范围查询包含两边边界值。

 

MultiFieldQueryParser 多字段查询器

示例

Query query = new MultiFieldQueryParser(new String[]{"name", "sn"}, analyzer).parse("Media-FX01");

应用场景:一个文档中含有“标题”,“正文”等字段,搜索一个关键词,不管它在标题中出现还是在正文中出现都算符合条件。这时,我们就用到了多域查询。

BooleanQuery 多条件查询器

支持字段类型

BooleanQuery 查询器支持的字段类型与子查询器有关,BooleanQuery本身并不创建查询具体条件只是拼接各种查询条件

示例

一个条件示例1:价格查询

            BooleanQuery.Builder builder = new BooleanQuery.Builder();
            Query price = LongPoint.newRangeQuery("price", 2000, 5000);

            builder.add(price, BooleanClause.Occur.SHOULD);

            BooleanQuery query = builder.build();

查询结果:

Lucene 9.x Query 查询器使用_图示-bc63e164036749ee9f89bf905cc0d17a.png

 

一个条件示例1:名称查询

            BooleanQuery.Builder builder = new BooleanQuery.Builder();

            Query name = new QueryParser("name",analyzer).parse("风扇");

            builder.add(name, BooleanClause.Occur.SHOULD);

            BooleanQuery query = builder.build();

查询结果:

Lucene 9.x Query 查询器使用_图示-e201e8c2d8f544c69f5a246fc66ac9a9.png

 

两个条件查询:或

            BooleanQuery.Builder builder = new BooleanQuery.Builder();
            Query price = LongPoint.newRangeQuery("price", 2000, 5000);
            Query name = new QueryParser("name",analyzer).parse("风扇");
            builder.add(price, BooleanClause.Occur.SHOULD);
            builder.add(name, BooleanClause.Occur.SHOULD);

            BooleanQuery query = builder.build();

查询结果:

Lucene 9.x Query 查询器使用_图示-6642016b211e4a16a650c1c565dd1006.png

两个条件查询:且

            BooleanQuery.Builder builder = new BooleanQuery.Builder();
            Query price = LongPoint.newRangeQuery("price", 2000, 5000);
            Query name = new QueryParser("name",analyzer).parse("风扇");
            builder.add(price, BooleanClause.Occur.MUST);
            builder.add(name, BooleanClause.Occur.MUST);
            BooleanQuery query = builder.build();

查询结果:

Lucene 9.x Query 查询器使用_图示-7575186505eb4eb0a3cb2271b2c7eb70.png

提示:没有结果是正常的,查看上面的两个单一查询,发现结果并没有交集,所以这里没找到结果;

 

两个条件:Filter

Filter:参与关系为 或,但是不参与评分

            BooleanQuery.Builder builder = new BooleanQuery.Builder();
            Query price = LongPoint.newRangeQuery("price", 2000, 5000);
            Query name = new QueryParser("name",analyzer).parse("风扇");
            builder.add(price, BooleanClause.Occur.SHOULD);
            builder.add(name, BooleanClause.Occur.FILTER);
            BooleanQuery query = builder.build();

查询结果:

Lucene 9.x Query 查询器使用_图示-7b66c85678454e1b82691f5c42b9889a.png

 

MultiSearcher与MultiReader

查询说名:一个查询,多个索引目录

  • 低版本使用MultiSearcher实现多索引目录集合查询,高版本使用MultiReader来实现
  • lucene6.2.1已经废弃了MultiSearcher这个类,改用MultiReader来实现。

示例

try (DirectoryReader reader1 = DirectoryReader.open(directory);
                 DirectoryReader reader2 = DirectoryReader.open(directory);
                 MultiReader multiReader = new MultiReader(reader1,reader2);
                 ){
                IndexSearcher indexSearcher = new IndexSearcher(multiReader);
                Query query = new QueryParser("sn", analyzer).parse("Media-FX01");
                System.out.println(query);
                TopDocs topDocs_10 = indexSearcher.search(query, 10);
            }

 


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
项目环境maven 项目&lt;properties&gtl; &lt;maven.compiler.source&gtl;17&lt;/maven.compiler.source&gtl; &...
需求用户的需求是多种多样的。比如:用户可能对中日关系比较感兴趣,想查找‘中’和‘日’挨得比较近(5个字的距离内)的文章,超过这个距离的不予考虑。比如:“中日双方
Lucene Field简介在 Apache Lucene 中,Field 类是文档中存储数据的基础。不同类型的 Field 用于存储不同类型的数据(如文本、数
Apache Lucene一款 Apache托管的全文索引组件,纯Java实现。Lucene的作用用户—&gtl;服务器—&gtl;Lucene API—&gtl;索引库—&gtl;数据库/文
背景介绍 Lucene是一款高性能、可扩展的信息检索工具库,是用于全文检索和搜寻的Java开放源码程序库,最初是由Doug Cutting所撰写,2000年发行
Apache lucene 与Java jdk版本对应关系表参考:Apache Lucene版本JDK版本备注
StandardAnalyzer自带的标准分词器源码示例 public static void main(String[] args) throws IOExc
mybatis Interceptor拦截器实现自定义扩展查询兼容mybatis plus @Intercepts({ @Signature(type = Executor.c...
接上一篇:mybatis Interceptor拦截器实现自定义扩展查询兼容mybatis plus-xqlee (blog.xqlee.com)这里进行自定义分页查询扩展,基于mybatis ...
Hibernate Search 入门配置及简单实用,在本文中,我们将讨论Hibernate Search的基础知识,如何配置它,并且我们将实现一些简单的查询。
Java编程使用原生JDBC查询数据库数据,并将返回结果赋值给JSON/JSONArray对象,用于返回数据。源码参考:import java.sql.Resu
MySQL慢查询优化_MySQL慢查询排查_MySQL慢查询设置配置
MySQL查询结果添加序号常规查询结果如下:SQL命令:SELECT * FROM test;​现在我们需要添加一行序列号,也就是1,2,3,4...那种
有些时候为了方便,会把多个值存在一个字段里面,然后用逗号分隔
Mysql FIND_IN_SET查询逗号分割字段某些情况下,我们存储的字符内容是以逗号分割多个内容的,例如下面的标签:这时候我们要查询tags包含骑行的记录,错误做法:(like 实现字符串包...