Lucene

依赖

<lunece.version>8.5.0</lunece.version>
 <!-- lucene核心库 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>${lunece.version}</version>
        </dependency>
        <!-- Lucene的查询解析器 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>${lunece.version}</version>
        </dependency>
        <!-- lucene的默认分词器库 -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>${lunece.version}</version>
        </dependency>
        <!-- ik分词器 -->
        <dependency>
            <groupId>com.jianggujin</groupId>
            <artifactId>IKAnalyzer-lucene</artifactId>
            <version>8.0.0</version>
        </dependency>

创建写索引

public void indexCreate(){
    try {
        FSDirectory directory = FSDirectory.open(Paths.get("F:\\lucene\\index\\example03"));
        StandardAnalyzer analyzer = new StandardAnalyzer();
        IndexWriter indexWriter = new IndexWriter(directory, new IndexWriterConfig(analyzer));

        Document doc1 = new Document();
        doc1.add(new IntField("id",1,Field.Store.YES));
        doc1.add(new StringField("name", "zhangsan", Field.Store.YES));
        doc1.add(new StringField("age", "15", Field.Store.YES));
        doc1.add(new StringField("test", "a", Field.Store.YES));
        doc1.add(new TextField("content", "百知教育 I love baizhi", Field.Store.YES));
        doc1.add(new Field("date", DateTools.dateToString(new Date(), Resolution.SECOND), StringField.TYPE_STORED));

        Document doc2 = new Document();
        doc2.add(new IntField("id",2,Field.Store.YES));
        doc2.add(new StringField("test", "e", Field.Store.YES));
        doc2.add(new StringField("age", "18", Field.Store.YES));
        doc2.add(new StringField("name", "lisi", Field.Store.YES));
        doc2.add(new TextField("content", "lucene实战开发 I love Lucene", Field.Store.YES));
        doc2.add(new Field("date", DateTools.dateToString(new Date(), Resolution.SECOND), StringField.TYPE_STORED));indexWriter.addDocument(doc1);
        indexWriter.addDocument(doc2);
        indexWriter.close();
        directory.close();
 } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }
    }

创建读索引

  FSDirectory directory = FSDirectory.open(Paths.get("F:\\lucene\\index\\example04"));
            IndexReader indexReader = DirectoryReader.open(directory);

            DirectoryReader directoryReader = DirectoryReader.openIfChanged((DirectoryReader) indexReader);
            if(directoryReader != null){
                indexReader.close();
                indexReader = directoryReader;
            }

            IndexSearcher searcher = new IndexSearcher(indexReader);

查询

常用Query查询

1. TermQuery

// 指定词元检索 第一个参数:field 第二个参数: term 词元
Query query = new TermQuery(new Term("content","百" ));

2. TermRangeQuery

// 范围检索(待测试)
Query query = new TermRangeQuery("name", new BytesRef("zh"),new BytesRef("an"), true, true);

3. NumericRangeQuery

// 按数字范围检索 第一个参数:field 第二个参数:start 第三个参数:end 第四个参数:是否包含start值 第五个参数: 是否包含end值
Query query = NumericRangeQuery.newIntRange("id", 2, 3, true,false);

4. PrefixQuery

// 按指定前缀检索
Query query = new PrefixQuery(new Term("name","lis"));

5. WildcardQuery

// 通配符检索 ? 表示占1个字符 * 匹配0-n个字符
Query query = new WildcardQuery(new Term("content","育*"));

6. FuzzyQuery

// 模糊检索 搜索的关键字即使有错,在一定范围内也可以查到
Query query = new FuzzyQuery(new Term("content","baiahi")); //baizhi

7. BooleanQuery

// 布尔检索
BooleanQuery.Builder  builder=new BooleanQuery.Builder();
TermQuery query1 = new TermQuery(new Term("content","百"));
TermQuery query2 = new TermQuery(new Term("name","zhangsan"));
// Occur.xxx 可选值:MUST--->必须存在 MUST_NOT--->必须不存在 SHOULD--->可有可无
query.add(query1,Occur.MUST_NOT); //第二个参数:查询的结果中 不要包含 "百" 文档
query.add(query2,Occur.MUST);

8. PhraseQuery

// 短语检索 一般适用于英文短句检索
PhraseQuery query = new PhraseQuery();
// slop是指两个项的位置之间允许的最大间隔距离
query.setSlop(1);
query.add(new Term("content","i"));
query.add(new Term("content","baizhi")); // 检索 i [**] baizhi 的所有文档
//排序
Sort sort = new Sort(new SortField(“id”, SortField.Type.LONG, true));
TopDocs topDocs = searcher.search(query, 10,sort);

基于QueryParser的高级搜索

public void indexSearchByQueryParser(){
    try {
        FSDirectory directory = FSDirectory.open(Paths.get("F:\\lucene\\index\\example03"));
        IndexReader indexReader = DirectoryReader.open(directory);

        DirectoryReader directoryReader = DirectoryReader.openIfChanged((DirectoryReader) indexReader);
        if(directoryReader != null) indexReader = directoryReader;

        // 创建检索器
        IndexSearcher searcher = new IndexSearcher(indexReader);

        // 创建查询解析器  第一个参数:指定默认检索域   第二个参数:分词器
        QueryParser queryParser = new QueryParser("content", new StandardAnalyzer());
        Query query = null;

        // 使用 parse(表达式) 可以完全替换Query查询
        // 分词检索
        query = queryParser.parse("百知");

        // 范围检索  不支持数值范围检索
        // test ---> 表示检索域   [a TO e] ---> test域中a到e的文档(包括a和e)
        query = queryParser.parse("test:[a TO e]");
        // test ---> 表示检索域   {a TO e} ---> test域中a到e的文档(不包括a和z)
        query = queryParser.parse("age:{10 TO 20}");

        // 通配符 检索
        query = queryParser.parse("百*");
        query = queryParser.parse("lo?e");
        query = queryParser.parse("baiz?i");

        // 模糊检索   ~ 表示模糊检索
        query = queryParser.parse("baizha~");
        query = queryParser.parse("lovi~");

        // 多条件检索
        //检索name中有zhangsan 或者 content中有lucene的文档
        query = queryParser.parse("name:zhangsan OR lucene");
        //检索name中有zhangsan 并且 content中有lucene的文档
        query = queryParser.parse("name:zhangsan AND baizhi"); 
        //检索name中有zhangsan 并且 content中没有lucene的文档
        query = queryParser.parse("name:zhangsan NOT lucene"); 

        // 短语检索
        query = queryParser.parse("content:\"love lucene\"");
        // 临近检索 :词组中的多个词之间的距离之和不超过1,则满足查询。
        query = queryParser.parse("content:\"i lucene\"~1");

        // 加权检索
        query = queryParser.parse("百知^0.1");

        // 布尔检索
        query = queryParser.parse("+love -name:zhangsan"); 
        query = queryParser.parse("love -baizhi");

        TopDocs topDocs = searcher.search(query, 10);
        System.out.println("查询结果:"+topDocs.totalHits+"条");
        System.out.println("最大文档数:"+indexReader.maxDoc());
        System.out.println("最大索引文档数:"+indexReader.numDocs());
        for(ScoreDoc sd : topDocs.scoreDocs){
            System.out.print(searcher.doc(sd.doc).get("id")+" | ");;
            System.out.print(searcher.doc(sd.doc).get("name")+" | ");;
            System.out.print(searcher.doc(sd.doc).get("content")+" | ");;
            System.out.print(DateTools.stringToDate(searcher.doc(sd.doc).get("date")));
            System.out.println();
        }
        indexReader.close();
        directory.close();
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

分页

    /**
     * 
     * @author gaozhy
     * @description 分页检索
     * @2017年4月14日 上午9:27:01
     */
    @Test
    public void indexSearchByPage() {

        try {
            FSDirectory directory = FSDirectory.open(Paths.get("F:\\lucene\\index\\example04"));
            IndexReader indexReader = DirectoryReader.open(directory);

            DirectoryReader directoryReader = DirectoryReader.openIfChanged((DirectoryReader) indexReader);
            if(directoryReader != null){
                indexReader.close();
                indexReader = directoryReader;
            }

            IndexSearcher searcher = new IndexSearcher(indexReader);
            QueryParser parser = new QueryParser("content", new StandardAnalyzer());
            Query query = parser.parse("name:张三*");

            //查所有
            //TopDocs topDocs = searcher.search(query, 100);

            int nowPage = 8;
            int pageSize = 10;

            // 获取起始条数   第三页   start=20
            int start = (nowPage-1)*pageSize; 

            // 查询当前页的前一条记录 根据query查20个文档
            TopDocs td1 = searcher.search(query, start);
            // 第一页  scoreDoc = null
            ScoreDoc scoreDoc = null;
            // 不是第一页 socreDoc = 第19个文档
            if (start > 1){
                scoreDoc = td1.scoreDocs[start-1];
            }

            //第一个参数:上一页查询到最后一条记录   第二个参数:查询条件    第二个参数:查询条数
            TopDocs topDocs = searcher.searchAfter(scoreDoc, query, pageSize);

            System.out.println("总条数:"+topDocs.totalHits);
            for (ScoreDoc sd : topDocs.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.print(doc.get("id")+" | ");
                System.out.print(doc.get("name")+" | ");
                System.out.print(doc.get("content"));
                System.out.println();
            }

            indexReader.close();
            directory.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

高亮查询

    @Test
    public void testHighlighter() throws Exception {
        //创建IndexReader对象,指定索引库保存的位置。
        IndexReader indexReader = DirectoryReader.open(FSDirectory.open(new File("C:\\Users\\JackChen\\Desktop\\index").toPath()));
        //创建IndexSearcher对象
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        //创建QueryPaser对象,两个参数
        QueryParser queryParser = new QueryParser("name", new IKAnalyzer());

        //使用QueryPaser对象创建一个Query对象,参数1:默认搜索域,参数2:分析器对象
        Query query = queryParser.parse("lucene.txt");

        //格式化对象,设置前缀和后缀
        Formatter formatter = new SimpleHTMLFormatter("<font color='red'>","</font>");
        //关键词对象
        QueryScorer scorer = new QueryScorer(query);
        //高亮对象
        Highlighter highlighter = new Highlighter(formatter, scorer);

        //执行查询
        TopDocs topDocs = indexSearcher.search(query, 10);
        System.out.println("总记录数:" + topDocs.totalHits);
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;
        //遍历查询结果
        for (ScoreDoc doc:scoreDocs){
            System.out.println("----------开始------------");
            //取文档id
            int docId = doc.doc;
            //根据id取文档对象
            Document document = indexSearcher.doc(docId);
            
            //设置内容高亮
            String highlighterContent = highlighter.getBestFragment(new StandardAnalyzer(),"name",document.get("name"));
            System.out.println(highlighterContent);
            
            document.getField("content");
            System.out.println(document.get("name"));
            System.out.println(document.get("content"));
            System.out.println(document.get("path"));
            System.out.println(document.get("size"));
            System.out.println("----------结束------------");
        }
        indexReader.close();
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梁晓山(ben)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值