学习笔记-----lucene入门

lucene
    

原理:

 

    lucene的检索算法属于索引检索,即用空间来换取时间,对需要检索的文件、字符流进行全文索引,在检索的时候对索引进行快速的检索,

    得到检索位置,这个位置记录检索词出现的文件路径或者某个关键词。

    
    在使用数据库的项目中,不使用数据库进行检索的原因主要是:数据库在非精确查询的时候使用查询语言“like %keyword%”,对数据库进行查询是对所有

    记录遍历,并对字段进行“%keyword%”匹配,在数据库的数据庞大以及某个字段存储的数据量庞大的时候,这种遍历是致命的,它需要对所有的记录进行

    匹配查询。因此,lucene主要适用于文档集的全文检索,以及海量数据库的模糊检索,特别是对数据库的 xml 或者大数据的字符类型。





一、建立索引的五个基础类 Document, Field, IndexWriter, Analyzer, Directory

    1、Document类:用来描述文档,这里的文档可以指一个HTML页面,一封电子邮件,或者是一个文本文件。一个 Document 对象由多个Field对象组成的。可以把一个Document对象想象成数据库中的一个记录,而每个Field对象就是记录的一个字段。

    2、Field类:用来描述一个文档的某个属性,比如一封电子邮件的标题和内容可以用两个Field对象分别描述。

    3、Analyzer类:用来对文档内容进行分词处理,Analyzer 类是一个抽象类,它有多个实现,针对不同的语言和应用需要选择适合的Analyzer,Analyzer会把分词后的内容交给IndexWriter来建立索引。

    4、IndexWriter类:用来创建索引的一个核心类,作用是把一个个的Document对象加到索引中来。

    5、Directory 类:表示索引文件存储位置的抽象类。有两个常用的子类:

    * FSDirectory — 在实际文件系统中存储索引的 Directory 实现。该类对于大型索引非常有用。
    * RAMDirectory — 在内存中存储所有索引的实现。该类适用于较小的索引,可以完整加载到内存中,在应用程序终止之后销毁。由于索引保存在内存中,所以速度相对较快。

 

二、搜索内容的四个基础类:Searche、Term、Query和TopDocs   

    1、Searcher 是一个抽象基类,包含各种超负荷搜索方法。IndexSearcher 是一个常用的子类,允许在给定的目录中存储搜索索引。Search 方法返回一个根据计算分数排序的文档集合。Lucene 为每个匹配给定查询的文档计算分数。IndexSearcher 是线程安全的;一个实例可以供多个线程并发使用。

    2、Term 是搜索的基本单位。它由两部分组成:单词文本和出现该文本的字段的名称。Term 对象也涉及索引编制,但是可以在 Lucene 内部创建。

    3、Query 和子类

    Query 是一个用于查询的抽象基类。搜索指定单词或词组涉及到在项中包装它们,将项添加到查询对象,将查询对象传递到 IndexSearcher 的搜索方法。

    Lucene 包含各种类型的具体查询实现,比如 TermQuery、BooleanQuery、PhraseQuery、PrefixQuery、RangeQuery、 MultiTermQuery、FilteredQuery、SpanQuery 等。以下部分讨论 Lucene 查询 API 的主查询类。

    4、TopDocs    封装搜索结果以及 ScoreDoc 的总数







例:
整体流程:
    1、存:
           1、创建一个Person对象
         * 2、创建一个IndexWriter对象
         * 3、把Person转化成field对象,然后添加到document中。
         * 4、把document添加到索引库中(indexWriter.add())
         * 5、关闭IndexWriter

public class ArticleIndex  {
    @Test
    public void add() throws Exception{
        Person person = new Person();
        person.setAge(20L);
        person.setName("王武");
        person.setDescription("很帅");//以上是建立一个对象,什么对象都可以。
        
        Directory directory = FSDirectory.open(new File("./database"));//设置一个路径指向,用于保存lucene库持久化信息的地方。
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);  //分析器(分词器),按照默认的标准进行分词操作。参数指定版本号
        
        IndexWriter indexWriter = new IndexWriter(directory, analyzer, MaxFieldLength.LIMITED);//建立流。
        Document document = new Document();                                                //建立document对象。
        Field ageField = new Field("年龄", person.getAge().toString(), Store.YES, Index.ANALYZED);         
        Field nameField = new Field("name", person.getName().toString(), Store.YES, Index.ANALYZED);
        Field descriptionField = new Field("description", person.getDescription().toString(), Store.YES, Index.ANALYZED);
        /**将数据保存在field中,其中的参数,
            
            第一个参数就是搜索时会扫描的内容,与queryParse中的对应。
            
            第二个参数 ,既是要存入的内容,必须是String。
            
            第三个参数 ,设置Store针对内容库存储,yes是存,NO是否。
            
            第四个参数 ,设置Index针对目录库
         *         no     不存
         *         not_analyzer  不分词存
         *         analyzer      分词存

        */
        document.add(descriptionField);
        document.add(nameField);
        document.add(ageField);
        indexWriter.addDocument(document);将所有内容添加进库中。
        indexWriter.close();            //切记一定要关流,因为lucene的流是带锁机制的,不关流其他流无法连接会报异常。
        
    }
    
    @Test
    public void find()throws Exception {
        List<Person> list = new ArrayList<Person>();
        FSDirectory directory = FSDirectory.open(new File("./database"));
        IndexSearcher indexSearcher = new IndexSearcher(directory);         //建立搜索流,指定库的路径
        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);
        QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_30, new String[]{"name","name","description"}, analyzer);

        //用于描述搜索的范围,在string数组中,选择要扫描的属性,查找与之对应的内容,与增加操作时的field的第一个参数对照。

        Query query = queryParser.parse("王武");        //此处填入的是搜索关键字。


        TopDocs topDocs = indexSearcher.search(query, 10); //2个参数 ,一个是将query传入,另一个则是当出现相同内容时,一共列出多少条。

        ScoreDoc[] scoreDocs = topDocs.scoreDocs;     //将搜索内容转换为数组。TopDocs是一个内部存放的都是Document对象的数组
        for(int i = 0;i<scoreDocs.length;i++){        
            Document document = indexSearcher.doc(scoreDocs[i].doc);//将内容取出。然后利用document对象为person赋值:最后输出
            Person person = new Person();
            person.setAge(Long.parseLong(document.get("年龄")));
            person.setDescription(document.get("description"));
            person.setName(document.get("name"));
            list.add(person);
        }
        for(Person person:list){
            System.out.println(person.getName());
            System.out.println(person.getAge());
            System.out.println(person.getDescription());
            
        }
        

    }

    @Test
    public void testDeleteIndex() throws Exception{
        /**
         * Term 关键词对象
         */
        IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
        /**
         * 该关键词对象包含了"title":"lucene"的关键词
         */
        Term term = new Term("title", "lucene");
        indexWriter.deleteDocuments(term);
        indexWriter.close();
    }

 //删除并不是真正的删除,而是增加一个新的标识文件。


         /**
     * 修改原理:先删除后增加
     * @throws Exception
     */
    @Test
    public void testUpdateIndex() throws Exception{
        /**
         * Term 关键词对象
         */
        
        Article article = new Article();
        article.setId(1L);
        article.setTitle("lucene可以做搜索引擎");
        article.setContent("aaaa");
        
        Term term = new Term("title","lucene");
        IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
        /**
         * term用于删除
         * document用于增加
         */
        indexWriter.updateDocument(term, DocumentUtils.article2Document(article));
        indexWriter.close();
    }


    @Test
    public void testOptimize() throws Exception{
        IndexWriter indexWriter = new IndexWriter(LuceneUtils.directory,LuceneUtils.analyzer,MaxFieldLength.LIMITED);
        indexWriter.optimize();//优化方法,可以将多个文件合并。并未深入学习,暂时了解
        indexWriter.close();
    }


}



IndexWriter的作用:

 * 1、同一个索引库在同一时刻内只能针对一个IndexWriter,如果出现两个IndexWriter,将会报错
 * 2、当创建一个IndexWriter的时候,indexWriter所指向的索引库就被上锁了(writer.lock文件)
 *    而这个时候不管用另外的IndexWriter还是IndexSearch去访问该索引库都访问不到
 * 3、当indexWriter被关闭的时候,writer.lock文件删除
 * 4、indexWriter的作用
 *             1、关闭资源
 *             2、释放锁资源

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值