`
TonyLian
  • 浏览: 402109 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

重新更新索引的方法

阅读更多

由于分词工具用的用户字典有了更新,比如加入了一些出现频度较高的专有名词。
这时候希望通过重建索引,使查询结果更加准确。
但是,由于一些信息是当初建索引时加入的,而且这些信息是不能从原始文件中提取的,如当初的上传者是谁、上传日期 等。所以,不能够直接删除索引文件,重新来过。

为此,必须遍历原有索引,将其中进行了分析的Field重新分析并更新,不需要分析的Field则保持不变。

 

/**
 * 为现有文件重新创建索引
 * 例如当更新了用户字典时使用
 */
public void rebuildIndex(){
    IndexReader ireader = null;
    IndexWriter iwriter = null;
    Directory directory = null;
    try {
        long start = new Date().getTime();
        //前期准备工作
        File indexPath = new File(SystemProperties.getIndexPath());
        directory = FSDirectory.open(indexPath);
        //实例化IKAnalyzer分词器
        Analyzer analyzer = new IKAnalyzer();
        //Analyzer analyzer = new CJKAnalyzer(Version.LUCENE_CURRENT);
        //建立内存索引对象
        ireader = IndexReader.open(directory);
        if (indexPath.list().length > 0) {
            // 已有以往索引
            iwriter = new IndexWriter(directory, analyzer, false, IndexWriter.MaxFieldLength.LIMITED);
        } else {
            // 首次建立索引
            iwriter = new IndexWriter(directory, analyzer, true, IndexWriter.MaxFieldLength.LIMITED);
        }
        //遍历每一已有Document
        for (int i = 0; i < ireader.maxDoc(); i++) {
            try {
                // 提取原Document
                Document oldDoc = ireader.document(i);
                // 创建新Document
                Document newDoc = new Document();
                // 不变的Field直接从原Document中取
                // KEY
                newDoc.add(oldDoc.getField(Constants.FEILD_NAME_KEY));
                // 文件名
                newDoc.add(oldDoc.getField(Constants.FEILD_NAME_CLIENTNAME)); 
                newDoc.add(oldDoc.getField(Constants.FEILD_NAME_SERVERNAME));
                // 文件类型
                newDoc.add(oldDoc.getField(Constants.FEILD_NAME_FILETYPE));
                // 加入时间
                newDoc.add(oldDoc.getField(Constants.FEILD_NAME_ADDTIME));
                // 所属部门,用户查询时的权限控制
                newDoc.add(oldDoc.getField(Constants.FEILD_NAME_OWNER));
                // 不变的Field从原Document中取得后,重新Analyse
                // 标题
                String title = oldDoc.getField(Constants.FEILD_NAME_TITLE).stringValue();
                newDoc.add(new Field(Constants.FEILD_NAME_TITLE, title, Field.Store.YES, Field.Index.ANALYZED));
                // 内容
                String text = oldDoc.getField(Constants.FEILD_NAME_CONTENTS).stringValue();
                newDoc.add(new Field(Constants.FEILD_NAME_CONTENTS, text, Field.Store.YES, Field.Index.ANALYZED));
                String key = oldDoc.getField(Constants.FEILD_NAME_KEY).stringValue();
                // 用KEY做查询条件
                Term term = new Term(Constants.FEILD_NAME_KEY, key);
                // 替换原有的Document
                iwriter.updateDocument(term, newDoc);   
            } catch (Throwable t) {
                if (log.isErrorEnabled()) {
                    log.error(t.getMessage());
                }
            }
        }
        long end = new Date().getTime();

        if (log.isDebugEnabled()) {
            log.debug("Rebuild Index: " + ireader.maxDoc() + " documents, in " + (end - start) + " milliseconds.");
        }
    } catch (Throwable t) {
        if (log.isErrorEnabled()) {
            log.error(t.getMessage());
        }
    } finally {
        if (ireader != null) {
            try {
                ireader.close();
            } catch (AlreadyClosedException e) {
                log.error(e.getMessage());
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
        if (iwriter != null) {
            try {
                // 注意这一句非常重要,否则虽然效果已经达到,但Documents数和存储空间都会翻倍!
                // 但使用此方法的前提是,磁盘剩余空间必须有已用索引空间的2倍
                // 此时由于重建,索引空间已经是翻倍的了,所以剩余空间应该有之前索引空间的4被!
                iwriter.optimize();
                iwriter.close();
            } catch (AlreadyClosedException e) {
                log.error(e.getMessage());
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
        if (directory != null) {
            try {
                directory.close();
            } catch (IOException e) {
                log.error(e.getMessage());
            }
        }
    }
}

 

刚刚接触Lucene时间不长,不知道以上自己“杜撰”的代码是否可行,请大家多多指点。

 

 

 

  • 大小: 3.2 KB
  • 大小: 622 Bytes
分享到:
评论
2 楼 wodettaworld 2012-10-24  
1 楼 TonyLian 2010-02-02  
今天发现一个小Bug。就是每次重建索引时,Documents的数量会翻番,索引所占用的磁盘空间也会翻番。

但是,在搜索时,确实只有一个版本,不存在重复的结果。

研究一番,发现,在关闭IndexWriter时,要对其进行“优化”。
它才会“压缩”空间,即被update的Document的被覆盖版本,才会被剔除,磁盘空间也会被释放。

// 在 iwriter.close(); 前加上这一句
iwriter.optimize();

相关推荐

    索引更新索引更新

    索引更新是Lucene中的一种重要机制,用于实时更新索引中的文档。索引更新可以分为两种情况:删除文档和更新文档。在Lucene中,删除文档可以使用IndexReader和IndexWriter两种方式实现,每种方式都有其优缺。 首先,...

    Mybatis Plus 自定义批量插入或批量更新(根据唯一索引)

    这个方法会先检查每个待插入对象是否已存在于数据库中,如果存在则调用 `updateById()` 进行更新,否则调用父类的 `batchInsert()` 方法进行插入。 对于批量更新,情况类似,但通常不需要检查数据是否存在,因为...

    SQL Server 索引结构及其使用(聚集索引与非聚集索引)

    但每个表只能有一个聚集索引,因为目录只能按照一种方法进行排序。 非聚集索引是目录纯粹是目录,正文纯粹是正文的排序方式。非聚集索引需要两个过程,先找到目录中的结果,然后再翻到所需的页码。非聚集索引的缺点...

    SQL Server 2000数据库中如何重建索引

    这种方法允许你在不删除旧索引的基础上重新创建它,减少了重建过程中的开销。当你对聚集索引执行此操作时,通常会涉及到所有关联的非聚集索引。如果直接删除并重新创建聚集索引,那么所有的非聚集索引都需要被删除...

    索引维护方法

    本文将深入探讨“索引维护方法”,并基于提供的描述和标签,讲解如何在Microsoft SQL Server环境中有效地进行索引维护。 首先,索引是数据库中的一个重要组成部分,它类似于书籍的目录,能够加速数据检索过程。索引...

    Oracle索引的访问方法,如何创建索引、查询索引、使用索引

    Oracle索引的访问方法和创建索引的知识点 Oracle索引的访问方法是一种数据库优化技术,旨在提高查询速度和数据检索效率。索引是一种数据结构,它可以快速定位和检索数据库中的数据。Oracle索引的访问方法包括创建...

    最简单的Lucene建立、搜索索引的方法

    - 索引更新时,应避免在搜索操作进行时修改索引,以防止数据不一致。 - 为了提高搜索效率,可以在创建索引时设置适当的参数,如`IndexWriterConfig`的`OpenMode`(决定是否覆盖现有索引)和`IndexingOptions`(决定...

    Solr数据库插入(全量和增量)索引

    通过以上测试结果,我们可以看到,Solr 数据库插入全量和增量索引可以正确地将数据插入 Solr 索引库中,并且可以实时地更新索引。在实际应用中,我们可以根据实际情况选择全量索引或增量索引,以满足不同的业务需求...

    关于lucene建立数据库索引的更新说明

    1. **资料的准确性**:由于网络上的信息繁多且质量参差不齐,使用Lucene时要确保所参考的教程或文档是最新的,因为版本更新可能导致某些方法或功能的改变。例如,旧版本中可能使用的`Hits`类在新版本中已被废弃,应...

    GAPI:GPU加速的移动对象并行索引方法.pdf

    实验结果表明,在处理高并发更新和数据分布不均的场景中,GAPI技术较传统索引方法有着明显的性能提升。具体来说,GAPI展现了更高的数据处理吞吐量和更低的系统响应时间,尤其在对象分布不均匀的环境下,性能优势更为...

    电信设备-一种全文检索系统中索引信息的更新方法以及装置.zip

    在电信设备上,由于数据量庞大且实时性要求高,如何快速、有效地更新索引信息就显得尤为重要。 索引信息的更新涉及到两个主要方面:一是新数据的引入,二是旧数据的修改或删除。当新的电信数据产生时,全文检索系统...

    SQL Server 2000索引结构及使用方法

    "SQL Server 2000 索引结构及使用方法" 本文将详细介绍 SQL Server 2000 的索引结构和使用方法,包括聚集索引和非聚集索引的定义、区别、使用场景和注意事项。 一、索引结构 索引是一种特殊的目录,可以帮助我们...

    Rtree索引方法C++源代码

    通过学习和理解这个Rtree索引方法的C++源代码,开发者可以深入掌握空间索引技术,提高处理大量多维数据时的性能,这对于开发地理信息系统软件、数据库索引优化或任何涉及空间查询的应用都是极其有价值的。

    XML数据索引技术

    本文将深入探讨当前XML索引技术的研究现状,分析现有索引方法的优点与不足,并展望未来的研究方向。 #### 二、XML索引技术概述 根据孔令波等人的研究,XML索引技术主要可以分为两大类:节点记录类索引和结构摘要类...

    Mysql数据库索引创建、索引删除、索引失效场景详解

    索引的失效场景包括:更新或删除索引列,使用不带索引的全表扫描操作,使用`SELECT *`而不是明确列出索引列,使用`NOT IN`、`&lt;&gt; ALL()`或`NOT EXISTS`等操作,以及在`WHERE`子句中使用了函数或表达式。此外,索引也...

    lucene索引优化多线程多目录创建索引

    5. **合并索引**:所有线程完成索引后,使用IndexWriter的`addIndexes()`方法将所有子索引合并到一个主索引中。 这个过程需要注意线程同步问题,确保在合并索引之前,所有线程已经完成了它们的工作,避免并发冲突。...

    电信设备-融合哈希的频繁更新不确定移动对象索引方法.zip

    为应对这些挑战,本文将深入探讨一种创新的解决方案——“融合哈希的频繁更新不确定移动对象索引方法”。 在开始具体讨论之前,先让我们明确什么是“不确定移动对象”。在现实应用中,不确定移动对象通常指的是那些...

    创建和优化索引 优化方法

    - 注意索引维护:重建或重新组织索引以保持其性能。 4. **全文搜索**: - 全文搜索允许对文本字段进行复杂的模糊匹配和自然语言搜索,对提供高级搜索体验非常有用。 5. **平衡索引策略**: - 在`custid`和`city...

    数据库用索引为什么比不用索引更快

    数据库中的索引是一种为了加速数据查询而创建的数据结构,它为表中的字段提供了一种快速访问的方法。在没有索引的情况下,数据库系统执行查询时必须进行全表扫描,即逐行检查直到找到所需数据,这在数据量大时效率极...

    数据结构课程设计 索引顺序查找

    如果未在索引中找到,可能需要进行全序列查找,或者更新索引结构。 4. **优化策略**:在某些情况下,如果索引不能精确定位到目标,可以采用分块索引或多级索引等技术,进一步提高查找效率。 在提供的文件中,"索引...

Global site tag (gtag.js) - Google Analytics