lucene+spring boot 基础入门代码

依赖

   <dependencies>
        <!-- Junit单元测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
        <!-- lucene核心库 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>4.10.2</version>
        </dependency>
        <!-- Lucene的查询解析器 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>4.10.2</version>
        </dependency>
        <!-- lucene的默认分词器库 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>4.10.2</version>
        </dependency>
        <!-- lucene的高亮显示 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-highlighter</artifactId>
            <version>4.10.2</version>
        </dependency>

        <dependency>
            <groupId>com.janeluo</groupId>
            <artifactId>ikanalyzer</artifactId>
            <version>2012_u6</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

扩展配置(词库更新不及时,可以省略,没有也能用)

创建索引

 @Test
    public void testCreateIndex(){


        try {
            //文档创建
            Document document = new Document();

            //添加一个字段,类型为long名称为id,值为10086
            document.add(new StringField("id","12306", Field.Store.YES));
            TextField textField = new TextField("title", "谷歌地图在全球范围还是有很大市场的", Field.Store.YES);

            //setBoost这个可以设置得分,越大得分排名越高
            textField.setBoost(10000);
            document.add(textField);
           //document.add(new StoredField("info","啦啦啦啦"));//只存储,不创建索引(不能用来搜索)

            //目录定义,使用open方法调用底层的工厂类,根据环境动态实现,最最佳匹配
            Directory directory = FSDirectory.open(new File("indexDir"));


            //分词器,由于中文分词器过时,所以使用标准分词器替代
            Analyzer analyzer = new IKAnalyzer();

            //索引写出的配置,需要指定版本和分词器
            IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST,analyzer);

            //设置目标索引库的打开方式,是追加,还是覆盖(重建),默认是追加或(重建)
            //indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE);//每次都新建

            //索引写出工具的创建,指定写出到哪里去,并且使用什么样的配置
            IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);

            indexWriter.addDocument(document);

            indexWriter.commit();

            //io流
            indexWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

批量创建索引

// 批量创建索引
    @Test
    public void testBatchCreateIndex() throws Exception{
        // 创建文档的集合
        Collection<Document> docs = new ArrayList<>();
        // 创建文档对象
        Document document1 = new Document();
        document1.add(new StringField("id", "1", Field.Store.YES));
        document1.add(new TextField("title", "谷歌地图之父跳槽facebook", Field.Store.YES));
        docs.add(document1);
        // 创建文档对象
        Document document2 = new Document();
        document2.add(new StringField("id", "2", Field.Store.YES));
        document2.add(new TextField("title", "谷歌地图之父加盟FaceBook", Field.Store.YES));
        docs.add(document2);
        // 创建文档对象
        Document document3 = new Document();
        document3.add(new StringField("id", "3", Field.Store.YES));
        document3.add(new TextField("title", "谷歌地图创始人拉斯离开谷歌加盟Facebook", Field.Store.YES));
        docs.add(document3);
        // 创建文档对象
        Document document4 = new Document();
        document4.add(new StringField("id", "4", Field.Store.YES));
        document4.add(new TextField("title", "谷歌地图之父跳槽Facebook与Wave项目取消有关", Field.Store.YES));
        docs.add(document4);
        // 创建文档对象
        Document document5 = new Document();
        document5.add(new StringField("id", "5", Field.Store.YES));
        document5.add(new TextField("title", "谷歌地图之父拉斯加盟社交网站Facebook", Field.Store.YES));
        docs.add(document5);

        // 索引目录类,指定索引在硬盘中的位置
        Directory directory = FSDirectory.open(new File("indexDir"));
        // 引入IK分词器
        Analyzer analyzer = new IKAnalyzer();
        // 索引写出工具的配置对象
        IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, analyzer);
        // 设置打开方式:OpenMode.APPEND 会在索引库的基础上追加新索引。
        // OpenMode.CREATE会先清空原来数据,再提交新的索引
        conf.setOpenMode(IndexWriterConfig.OpenMode.CREATE);

        // 创建索引的写出工具类。参数:索引的目录和配置信息
        IndexWriter indexWriter = new IndexWriter(directory, conf);
        // 把文档集合交给IndexWriter
        indexWriter.addDocuments(docs);
        // 提交
        indexWriter.commit();
        // 关闭
        indexWriter.close();
    }

删除索引(更新就是删除+新增)

 @Test
    public void testDeleteIndex() throws IOException {


        //目录定义,使用open方法调用底层的工厂类,根据环境动态实现,最最佳匹配
        Directory directory = FSDirectory.open(new File("indexDir"));


        //分词器,由于中文分词器过时,所以使用标准分词器替代
        Analyzer analyzer = new IKAnalyzer();

        //索引写出的配置,需要指定版本和分词器
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LATEST,analyzer);

        //设置目标索引库的打开方式,是追加,还是覆盖(重建),默认是追加或(重建)
        //indexWriterConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE);//每次都新建

        //索引写出工具的创建,指定写出到哪里去,并且使用什么样的配置
        IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);


        //删除所有
        //indexWriter.deleteAll();

        //先查询再删除,词条式,要求,词条必须存在,并且删除的字段类型不能是数值类型
        //indexWriter.deleteDocuments(new Term("title","谷歌地图"));
        //indexWriter.deleteDocuments(new Term("id","3"));


        //根据需求创建query对象,根据query对象,查询内容,查询到多少,删除多少
        Query query = null;

        indexWriter.deleteDocuments(query);


        indexWriter.commit();

        //io流
        indexWriter.close();
    }

基础查询

  • 封装的查询方法
public void commonSearch(Query query) throws Exception {

        //要指定目录
        Directory directory = FSDirectory.open(new File("indexDir"));

        //创建一个索引读取的对象,从索引库中读取索引
        IndexReader indexReader = DirectoryReader.open(directory);

        //索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);


        //search搜索方法,传入,传入搜索条件,得到搜索的结果,
        //query 表示搜索的条件
        //n 需要的前n个,数量的指定和最终的结果,会有出入,如果查询命中的个数大于n,则显示n个,如果小于n,有多少显示多少,不会报错
        TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE);

        //totalHits查询命中的数量,
        int totalHits = topDocs.totalHits;

        //scoreDocs是查询文档的集合结果  doc表示文档的编号,score,表示得分

        ScoreDoc[] scoreDocs = topDocs.scoreDocs;


        System.out.println("命中文档个数:" + totalHits);

        for (ScoreDoc scoreDoc : scoreDocs) {
            System.out.println("============================================");
            int docID = scoreDoc.doc;//文档id
            float score = scoreDoc.score;//文档得分

            //根据文档的id获取到对应的文档
            Document document = indexSearcher.doc(docID);

            //从文档中取出对应的属性,对应的值
            String id = document.get("id");
            String title = document.get("title");

            System.out.println("score:" + score + " id:" + id + " title:" + title);
        }
    }
  • 查询
    @Test
    public void testQueryIndex() throws Exception {

        //查询条件的转换封装工具,这里的分词器一定要和创建索引用的分词器一致
        QueryParser queryParser = new QueryParser("title", new IKAnalyzer());

        Query query = queryParser.parse("谷歌地图");


        commonSearch(query);
    }


    /*
     * 注意:Term(词条)是搜索的最小单位,不可再分词。值必须是字符串!
     */
    @Test
    public void testTermQuery() throws Exception {
        // 创建词条查询对象
        Query query = new TermQuery(new Term("title", "谷歌"));
        commonSearch(query);
    }


    /* 通配符查询:
     * 	? 可以代表任意一个字符
     * 	* 可以任意多个任意字符
     */
    @Test
    public void testWildCardQuery() throws Exception {
        // 创建查询对象
        Query query = new WildcardQuery(new Term("title", "*谷歌"));
        commonSearch(query);
    }

    /*
     * 测试模糊查询
     */
    @Test
    public void testFuzzyQuery() throws Exception {
        // 创建模糊查询对象:允许用户输错。但是要求错误的最大编辑距离不能超过2
        // 编辑距离:一个单词到另一个单词最少要修改的次数 facebool --> facebook 需要编辑1次,编辑距离就是1
        // Query query = new FuzzyQuery(new Term("title","fscevool"));
        // 可以手动指定编辑距离,但是参数必须在0~2之间
        Query query = new FuzzyQuery(new Term("title","facabooc"),1);
        commonSearch(query);
    }


    /*
     * 数值范围查询
     */
    @Test
    public void testNumericRangQuery() throws Exception {

        //5个参数,分别表示
       Query query = NumericRangeQuery.newLongRange("id",12306L,12306L,true,true);
        commonSearch(query);
    }


    /*
     * 组合查询
     *
     * MUST VS MUST   &&  交集
     *
     * SHOULD VS SHOULD  || 并集
     *
     * MUST VS MUST_NOT  ! 取反
     */
    @Test
    public void testBooleanQuery() throws Exception {

        //5个参数,分别表示
        Query query1 = NumericRangeQuery.newLongRange("id",2L,4L,true,true);
        Query query2 = NumericRangeQuery.newLongRange("id",3L,5L,true,true);

        BooleanQuery query = new BooleanQuery();

        query.add(query1, BooleanClause.Occur.MUST);
        query.add(query2, BooleanClause.Occur.MUST);

        commonSearch(query);
    }

高级查询

  • 高亮查询`
@Test
    public void highlightSearch() throws Exception {

        //要指定目录
        Directory directory = FSDirectory.open(new File("indexDir"));

        //创建一个索引读取的对象,从索引库中读取索引
        IndexReader indexReader = DirectoryReader.open(directory);

        //索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //查询条件的转换封装工具,这里的分词器一定要和创建索引用的分词器一致
        QueryParser queryParser = new QueryParser("title", new IKAnalyzer());

        Query query = queryParser.parse("谷歌地图");


        //search搜索方法,传入,传入搜索条件,得到搜索的结果,
        //query 表示搜索的条件
        //n 需要的前n个,数量的指定和最终的结果,会有出入,如果查询命中的个数大于n,则显示n个,如果小于n,有多少显示多少,不会报错
        TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE);

        //totalHits查询命中的数量,
        int totalHits = topDocs.totalHits;

        //scoreDocs是查询文档的集合结果  doc表示文档的编号,score,表示得分

        ScoreDoc[] scoreDocs = topDocs.scoreDocs;


        System.out.println("命中文档个数:" + totalHits);

        //准备高亮工具
        //指定格式化的格式,<em></em>
        Formatter formatter = new SimpleHTMLFormatter("<em>", "</em>");
        Scorer scorer = new QueryScorer(query);
        Highlighter highlighter = new Highlighter(formatter, scorer);

        for (ScoreDoc scoreDoc : scoreDocs) {
            System.out.println("============================================");
            int docID = scoreDoc.doc;//文档id
            float score = scoreDoc.score;//文档得分

            //根据文档的id获取到对应的文档
            Document document = indexSearcher.doc(docID);

            //从文档中取出对应的属性,对应的值
            String id = document.get("id");

            String result = document.get("title");

            //对result结果进行二次分词并且在分词结果基础上,如果词条和搜索词条一致,则高亮
            String highlighterTitle = highlighter.getBestFragment(new IKAnalyzer(), "title", result);

            System.out.println("score:" + score + " id:" + id + " title:" + highlighterTitle);
        }
    }
  • 排序查询
  @Test
    public void sortSearch() throws Exception {

        //要指定目录
        Directory directory = FSDirectory.open(new File("indexDir"));

        //创建一个索引读取的对象,从索引库中读取索引
        IndexReader indexReader = DirectoryReader.open(directory);

        //索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //查询条件的转换封装工具,这里的分词器一定要和创建索引用的分词器一致
        QueryParser queryParser = new QueryParser("title", new IKAnalyzer());

        Query query = queryParser.parse("谷歌地图");


        //search搜索方法,传入,传入搜索条件,得到搜索的结果,
        //query 表示搜索的条件
        //n 需要的前n个,数量的指定和最终的结果,会有出入,如果查询命中的个数大于n,则显示n个,如果小于n,有多少显示多少,不会报错
        //排序的条件
        Sort sort = new Sort(new SortField("id", SortField.Type.STRING));

        TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE, sort);

        //totalHits查询命中的数量,
        int totalHits = topDocs.totalHits;

        //scoreDocs是查询文档的集合结果  doc表示文档的编号,score,表示得分

        ScoreDoc[] scoreDocs = topDocs.scoreDocs;


        System.out.println("命中文档个数:" + totalHits);


        for (ScoreDoc scoreDoc : scoreDocs) {
            System.out.println("============================================");
            int docID = scoreDoc.doc;//文档id
            float score = scoreDoc.score;//文档得分

            //根据文档的id获取到对应的文档
            Document document = indexSearcher.doc(docID);

            //从文档中取出对应的属性,对应的值
            String id = document.get("id");

            String result = document.get("title");


            System.out.println("score:" + score + " id:" + id + " title:" + result);
        }
    }
  • 分页查询
 @Test
    public void pageSearch() throws Exception {
        int page = 5555;
        final Integer SIZE = 2;
        int start = (page - 1) * SIZE;
        int end = page * SIZE;


        //要指定目录
        Directory directory = FSDirectory.open(new File("indexDir"));

        //创建一个索引读取的对象,从索引库中读取索引
        IndexReader indexReader = DirectoryReader.open(directory);

        //索引的搜索对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //查询条件的转换封装工具,这里的分词器一定要和创建索引用的分词器一致
        QueryParser queryParser = new QueryParser("title", new IKAnalyzer());

        Query query = queryParser.parse("谷歌地图");


        //search搜索方法,传入,传入搜索条件,得到搜索的结果,
        //query 表示搜索的条件
        //n 需要的前n个,数量的指定和最终的结果,会有出入,如果查询命中的个数大于n,则显示n个,如果小于n,有多少显示多少,不会报错
        //排序的条件
        Sort sort = new Sort(new SortField("id", SortField.Type.STRING));

        TopDocs topDocs = indexSearcher.search(query, Integer.MAX_VALUE, sort);

        //totalHits查询命中的数量,
        int totalHits = topDocs.totalHits;

        //scoreDocs是查询文档的集合结果  doc表示文档的编号,score,表示得分

        ScoreDoc[] scoreDocs = topDocs.scoreDocs;


        System.out.println("命中文档个数:" + totalHits);

        int totalPage = totalHits % SIZE == 0 ? totalHits / SIZE : totalHits / SIZE + 1;

        if (page>totalPage){
            System.out.println("抱歉没有,gun");
            return;
        }else if (page==totalPage){//最后一页,不应该算,最后一页的数量要以实际数量为准
            end = totalHits;

        }


        for (int i = start; i < end; i++) {

            ScoreDoc scoreDoc = scoreDocs[i];
            int docID = scoreDoc.doc;//文档id
            float score = scoreDoc.score;//文档得分

            //根据文档的id获取到对应的文档
            Document document = indexSearcher.doc(docID);

            //从文档中取出对应的属性,对应的值
            String id = document.get("id");

            String result = document.get("title");


            System.out.println("score:" + score + " id:" + id + " title:" + result);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值