Lucene全文检索(一)

全文检索的概念

1.从大量的信息中快速、准确的查找要的信息
2.收索的内容是文本信息
3.不是根据语句的意思进行处理的(不处理语义)
4.全面、快速、准确是衡量全文检索系统的关键指标。
5.搜索时英文不区分大小写,结果列表有相关度排序。

全文检索与数据库搜索的区别

1.数据库搜索
Eg: select * from article where content like ‘%here%’
结果where  here
缺点:
1).搜索效果比较差
2).在搜索的结果中,有大量的数据被搜索出来,有很多数据是没有用的
3).查询速度在大量数据的情况下是很难做到快速的
2.全文检索
1).搜索结果按相关度排序,这意味着只有前几个页面对用户来说是比较有用的,其他的结果与用户想要的答案可能相差甚远。数据库搜索时做不到相关度排序的。
2).因为全文检索是采用索引的方式,所以在速度上肯定比数据库方式like要快。
3).所以数据库不能代替全文检索。

Lucene

Lucene:全文检索只是一个概念,而具体实现有很多框架,lucene是其中的一种。

Lucene结构图

说明:
1.索引库中的索引数据是在磁盘上存在的,我们用Directory这个类来描述。
2.我们可以通过API来实现对索引库的增、删、改、查的操作
3.在索引库中各种数据形式可以抽象出一种数据格式Document
4.Document的结构为:Document(List<Field>)
5.Field里存放一个键值对。键值对都为字符串的形式。
6.对索引库中索引的操作实际上也是对Document的操作。

Lucene入门案例

1.搭建工程环境,并导入所需的jar包,至少需要以下四个jar包
lucene-core-3.1.0.jar(核心包)
lucene-analyzers-3.1.0.jar(分词器)
lucene-highlighter-3.1.0.jar(高亮器)
lucene-memory-3.1.0.jar(高亮器)
2.建立索引
步骤:
1)创建IndexWriter对象
2)把JavaBean转化为Document
3)利用IndexWriter.addDocument方法增加索引
4)关闭资源
Eg:

package cn.lsl.lucene.demo;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

/*
 * 功能1:把一个文章放入索引库中
 * */
public class LuceneDemo {

    @Test
    public void testCreatIndex() throws IOException{
        //1.获取文章内容
        Article article = new Article();
        article.setId(1);
        article.setTitle("lucene");
        article.setContent("提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。");
        //把文章放入到索引库中
        Directory directory = FSDirectory.open(new File("./indexDir"));    //Directory 索引库
        //分词器
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
        //构造indexWriter对象
        IndexWriter indexWriter = new IndexWriter(directory,analyzer,MaxFieldLength.LIMITED);
        //把Article转化为Document
        Document doc = new Document();
        Field idField = new Field("id",article.getId().toString(), Store.YES, Index.NOT_ANALYZED);
        Field titleField = new Field("title",article.getTitle(),Store.YES,Index.ANALYZED);
        Field contentField = new Field("content",article.getContent(), Store.YES, Index.ANALYZED);
        doc.add(idField);
        doc.add(titleField);
        doc.add(contentField);
        indexWriter.addDocument(doc);
        indexWriter.close();
    }
}

原理图

注:Store这个参数表明是否将内容存放到索引内容中

Index这个参数表明是否存放关键字到索引目录中。

3.进行搜索
步骤:
1)创建IndexSeacher对象
2)创建Query对象
3)进行搜索
4)获得总结果数和前N行记录ID列表
5)根据目录ID把列表Document转化为JavaBean并放入集合中
6)循环出要检索的内容
Eg:

package cn.lsl.lucene.demo;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

/*
 * 功能:从索引库中把文章检索出来
 * */
public class LuceneDemo {

    //从索引库中吧文章检索出来

    @Test
    public void testSearch() throws IOException, ParseException{
        //1.创建IndexSearch对象
        Directory directory = FSDirectory.open(new File("./indexDir"));
        IndexSearcher indexSearcher = new IndexSearcher(directory);
        //2.创建Query对象
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
        QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new String[]{"title","content"},analyzer);
        //参数为要检索的关键字
        Query query = queryParser.parse("lucene");
        //3.进行搜索
        //query 搜索的条件, 显示N行记录,TopDocs 目录的结果
        TopDocs topDocs = indexSearcher.search(query, 10);
        //4.获取总记录数和前N行的目录ID列表
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;

        int count = topDocs.totalHits;    //总记录数
        System.out.println("总记录数:" + count);

        //5.根据目录的行ID获取每行的document,并吧Article放入集合中
        List<Article> articleList = new ArrayList<Article>();
        for (int i = 0; i < scoreDocs.length; i++) {
            int index = scoreDocs[i].doc;    //索引位置,即目录列表ID
            float score = scoreDocs[i].score;    //相关度得分
            System.out.println("得分:"+ score);
            Document document = indexSearcher.doc(index);
            //把Document转化为Article
            Article article = new Article();
            article.setId(Integer.valueOf(document.get("id").toString()));
            article.setTitle(document.get("title"));
            article.setContent(document.get("content"));
            articleList.add(article);
        }

        for (Article article : articleList) {
            System.out.println("id:" + article.getId());
            System.out.println("title:" + article.getTitle());
            System.out.println("content:" + article.getContent());
        }
    }
}

原理图:

保持数据库与索引库同步

在一个系统中,如果索引功能存在,那么数据库和索引库应该是同时存在的。这个时候需要保证索引库的数据和数据库中的数据保持一致性。可以在对数据库进行增删改查操作的同时对索引库也进行相应的操作。这样就可以保持数据库与索引库的一致性。

Lucene的增删改查及API详解

创建工具类:

LuceneConfig.java

package cn.lsl.lucene.util;

import java.io.File;
import java.io.IOException;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

public class LuceneConfig {
    public static Analyzer analyzer;
    public static Directory directory;
    static{
        try {
            analyzer = new StandardAnalyzer(Version.LUCENE_30);
            directory = FSDirectory.open(new File("./indexDir"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注意:LuceneConfig这个类对Directory和Analyzer进行了包装。

因为在创建IndexWriter时,需要用到这两个类,而管理索引库的操作也都要用到IndexWriter这个类,所以我们对Directory和Analyzer进行了包装

LuceneUtils.java

package cn.lsl.lucene.util;

import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;

public class LuceneUtils {
    public static IndexWriter indexWriter;

    private LuceneUtils(){}

    public static IndexWriter getIndexWriter() throws Exception {
        if(indexWriter == null){
            indexWriter = new IndexWriter(LuceneConfig.directory,LuceneConfig.analyzer,MaxFieldLength.LIMITED);
        }
        return indexWriter;
    }
}

LuceneUtils类对创建IndexWriter进行了封装

因为在一个索引库中只能存在一个IndexWriter对象。(同一个索引库只能有一个IndexWriter进行操作)

所以我们这里采用了单例的模式进行了封装。

DocumentUtils.java

(把JavaBean封装成Document和把Document封装成JavaBean的过程。)

package cn.lsl.lucene.util;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.util.NumericUtils;
import cn.lsl.lucene.demo.Article;

public class DocumentUtils {
    public static Document article2Document(Article article){
        Document document = new Document();
        Field idField = new Field("id",article.getId().toString(), Store.YES, Index.NOT_ANALYZED);
        Field titleField = new Field("title",article.getTitle(), Store.YES, Index.ANALYZED);
        Field contentField = new Field("content",article.getContent(), Store.YES, Index.ANALYZED);
        document.add(idField);
        document.add(titleField);
        document.add(contentField);
        return document;
    }

    public static Article document2Article(Document document){
        Article article = new Article();
        article.setId(Integer.valueOf(document.get("id")));
        article.setTitle(document.get("title"));
        article.setContent(document.get("content"));
        return article;
    }
}

什么情况下使用Index.NOT_ANALYZED

当这个属性的值代表的是一个不可分割的整体,例如ID

什么情况下使用Index.ANALYZED

当这个属性的值代表是一个可分割的整体

LuceneManager.java(增删改查例子)

package cn.lsl.lucene.manager;

import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.util.Version;
import org.junit.Test;

import cn.lsl.lucene.demo.Article;
import cn.lsl.lucene.util.DocumentUtils;
import cn.lsl.lucene.util.LuceneConfig;
import cn.lsl.lucene.util.LuceneUtils;

public class LuceneManager {

    @Test
    public void testCreateIndex() throws Exception{
        IndexWriter indexWriter = LuceneUtils.getIndexWriter();
        Article article = new Article();
        article.setId(1);
        article.setTitle("lucene");
        article.setContent("全文检索");
        Document doc = DocumentUtils.article2Document(article);
        indexWriter.addDocument(doc);
        indexWriter.close();
    }

    @Test
    public void testUpdateIndex() throws Exception{
        IndexWriter indexWriter = LuceneUtils.getIndexWriter();
        Term term = new Term("id","1");
        Article article = new Article();
        article.setId(1);
        article.setTitle("baidu");
        article.setContent("百度一下,你就知道");
        /*term 关键字  用来进行删除的
         * document 是用来进行增加的
         * */
        indexWriter.updateDocument(term, DocumentUtils.article2Document(article));
        indexWriter.close();
    }

    @Test
    public void testDeleteIndex() throws Exception{
        IndexWriter indexWriter = LuceneUtils.getIndexWriter();
        //term 关键字
        Term term = new Term("id","1");
        indexWriter.deleteDocuments(term);
        indexWriter.close();
    }

    @Test
    public void testQueryIndex() throws Exception{
        IndexSearcher indexSearcher = new IndexSearcher(LuceneConfig.directory);

        List<Article> articleList = new ArrayList<Article>();
        QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new String[]{"title","content"}, LuceneConfig.analyzer);
        Query query = queryParser.parse("lucene");
        TopDocs topDocs = indexSearcher.search(query, 10);    //索引库
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;//索引库数组
        int count = topDocs.totalHits;    //总记录数
        for (int i = 0; i < scoreDocs.length; i++) {
            int index = scoreDocs[i].doc;    //得到相关的索引
            float score = scoreDocs[i].score;    //相关度得分
            Document document = indexSearcher.doc(index);
            Article article = DocumentUtils.document2Article(document);
            articleList.add(article);
        }

        for (Article article : articleList) {
            System.out.println(article.getId());
            System.out.println(article.getTitle());
            System.out.println(article.getContent());
        }
    }
}
时间: 2024-12-29 15:26:09

Lucene全文检索(一)的相关文章

jQuery、HTML5、Spring Security安全权限、Lucene全文检索

获取[下载地址]   QQ: 313596790   [免费支持更新]支持三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体[新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统]A 代码生成器(开发利器);      增删改查的处理类,service层,mybatis的xml,SQL( mysql   和oracle)脚本,   jsp页面 都生成   就不用写搬砖的代码了,生成的放到项目里,可以直接运行B 阿里巴巴数据库连接池druid

Lucene全文检索

 全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本.全面.准确和快速是衡量全文检索系统的关键指标. l关于全文检索,我们要知道: 1,只处理文本. 2,不处理语义. 3,搜索时英文不区分大小写. 4,结果列表有相关度排序. l在信息检索工具中,全文检索是最具通用性和实用性的. Lucene全文检索

Spring MVC、Mybatis、Hibernate、Bootstrap、jQuery、HTML5、Spring Security安全权限、Lucene全文检索、Ehcache分布式缓存 、高性能、高并发【Java企业通用开发平台框架】

获取[下载地址]   QQ: 313596790   [免费支持更新] A 代码生成器(开发利器);    B 阿里巴巴数据库连接池druid;   数据库连接池  阿里巴巴的 druid.Druid在监控.可扩展性.稳定性和性能方面都有明显的优势 C 安全权限框架shiro ;  D ehcache 自定义二级缓存; E 微信接口开发(后续会加入Activiti5 工作流 )免费升级 -------------------------------------------------------

【Lucene】Apache Lucene全文检索引擎架构之入门实战

Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟的免费开源工具.就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库.--<百度百科> 这篇博文主要从两个方面出发,首先介绍一下Lucene中的全文搜索原理,其次通过程序示例来展现如何使用Lucene.关于全文搜索原理部分我上网搜索了一下,也看了好几篇文章,最后在写这篇文

lucene全文检索技术

1:lucene的介绍 全文检索引擎工具包.作用:使用lucene进行全文检索 .可以直接运行. 什么是全文检索.全文检索的场景,搜索引擎,搜索商品. 站内搜索,只会搜索自己站内的资源 全文检索首先将要查询的目标文档中的词提取出来,组成索引,通过查询索引达到搜索的文档的目的 这种先建立索引,在对索引进行搜索的过程就叫全文检索. 索引就类似于书籍的目录,目标文档就相当于书籍中的内容 搜索书籍中的内容,如果不通过目录,很费劲 其实,全文检索就是相当于给书籍编写目录. 2:Lucene实现全文检索的流

Lucene全文检索之-Lucene基础

Lucene是全文检索引擎 一.在学习Lucene之前我们先思考下,Lucene存在的意义. 1.在之前我们的应用场景中,基于数据库的检索,我们使用like语法进行.但是基于like语法效率低下.达不到我们对应用的使用要求. 而使用Lucene对我们的数据建立索引效率高速度快,满足企业要求. 我们使用Lucene先对整个结构建立索引库,然后根据索引去查找我们需要匹配的内容,效率高速度快,方便我们快速检索信息-这也是Lucene存在的目的. 2.有些查找数据库做不了,比如我们想查找附件中内容的匹配

Lucene全文检索入门体验

Lucene是Apache开源的全文检索框架, 是单纯的搜索工具, 简单易用. 现在已经出到5.2.1的版本, 只需在项目中导入必需的几个jar包就能使用. 使用的过程可以概括为, 1)  建立索引 2) 搜索查找, 获取搜索结果 这里我们一起先来学习几个会用到的核心类: Directory 该类在Lucene中用于描述索引存放的位置信息. 比如: Directory dir = FSDirectory.open(Paths.get("c:\\lucene\\index")); 其中&

Lucene全文检索学习入门

今天开始接触Lucene搜索,Lucene是一个全文检索的框架,主要适用于搜索,这里的搜索不同于天龙八部私服数据库的查询.Lucene是建立索引然后存在你设置的路径或者内存中,然后当你输入条件的时候就会去索引文件检索查询.Lucene能够实现分词和查询结构高亮的功能,而且在其强大的天龙八部私服架构下全文检索的速度是比较快的.由于Lucene将数据分词后以索引方式存储,这就势必会占内存或空间(Lucene的索引存储一般有文件存储和内存存储2种方式),我们就会将不必要的东西不存储.而我们一般在使用L

Lucene全文检索基础

---------------------------------------------------------------------------------------------------------------[版权申明:本文系作者原创,转载请注明出处]文章出处:http://blog.csdn.net/sdksdk0/article/details/51873672作者:朱培     ID:sdksdk0 --------------------------------------