Lucene 入门 06 - 索引库的维护

咩是索引库的维护 ?
再来一个大白话: 就是针对创好的索引库进行增删改查. 够不够直白.

在前几章说过了创建索引库, 但是在创建 Field 的时候, 使用的都是 TextField.
其实 Field 也是分好多属性的.

Field 域的属性

  1. 是否需要进行分词

    • 前提是这个字段首先要创建索引。然后如果这个字段的值是不可分割的,那么就不需要分词。例如:ID
  2. 是否需要创建索引

    • 将 Field 分析后的词或整个 Field 值进行索引, 只有索引方可搜索到. 比如: 商品名称, 商品简介 分析后进行索引, 订单号, 身份证号不用分析, 但也要索引. 这些将来都要作为查询条件
  3. 是否需要存储

    • 将 Field 值存储在文档中, 存储在文档中的 Field 才可以从 Document 中获取.比如:商品名称, 订单号, 凡是将来要从 Document 中获取的 Field 都要存储.
    • 这个简单来说, 只要是一个字段最终要显示到结果中的, 那么就一定要存储. 否则不存储.

1. Field 域的类型

在创建域的时候, 根据实际的数据类型, 来选择域的类型进行创建

Field 类 数据类型 Analyzed 是否分析 Indexed 是否索引 Stored 是否存储 说明
String Field(FieldName, FieldValue , Store.YES) 字符串 N Y Y 或N 这个Field 用来构建一个字符串Field, 但是不会进行分析, 会将整个字符串存储在索引中. 比如(订单号, 姓名等). 是否存储在文档中用 Store.YES / Store.NO决定
LongPoint(String name, long point),intPoint ...... Long 型 Y Y N 可以使用 LongPoint, IntPoint 等类型存储数值类型的数据, 让数值类型可以进行索引. 但是不能存储数据, 如果想存储数据还需要使用 StoreField
StoreField(FieldName, FieldValue) 重载方法, 支持多种类型 N N Y 这个 Field 用来构建不同类型的 Field, 不拆分,不索引, 但要 Field 存储在文档中, 比如路径等信息.
TextField(FieldName, FieldValue, Store.NO) 或
TextFiled(FieldName, reader)
字符串 或流 Y Y Y 或 N 如果是一个 Reader, Lucene猜测内容比较多, 会采用 Unstored 的策略

2. 代码改造.

现在我们知道了域的属性后, 对最开始我们的索引库创建进行代码改造.
Lucene 入门 03 - 全文检索创建的代码实现

  • 路径 "path" 我们只需要存储就行了,不需要分析, 所以要换成 StoreField.
  • 文件大小"size" 我们不需要进行存储, 但是我们可能又需要计算例如按大小来过滤. 那么使用 LongPoint 来分析并添加索引,但不存储, 使用 StoredField 来存储.

改造后代码如下:

    @Test
    public void createIndex() throws Exception {
        //1.创建一个 Director 对象, 指定索引库保存的位置.把索引保存在磁盘
        Directory mDirectory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
        //2. 创建一个 IndexWriter 对象
        //不再使用默认的分析器, 使用 IK
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(new IKAnalyzer());
        IndexWriter indexWriter = new IndexWriter(mDirectory, indexWriterConfig);

        //读取磁盘上的文件 (我磁盘上放了几个 text)
        File dir = new File("/Users/yzhang/Desktop/searchsource");
        File[] files = dir.listFiles();
        for (File file : files) {
            String fileName = file.getName();
            String filePath = file.getPath();
            String fileContent = FileUtils.readFileToString(file, "utf-8");
            long fileSize = FileUtils.sizeOf(file);
            //3. 创建域
            //args1: 域的名称. args2: 域的内容. args3:是否存储到磁盘
            Field fieldName = new TextField("name", fileName, Field.Store.YES); 
            //变为 StoreField         
            Field fieldPath = new StoredField("path", filePath);
            Field fieldContent = new TextField("content", fileContent, Field.Store.YES);
            //使用 LongPoint 进行分析和索引
            Field fieldSizeValue = new LongPoint("size", fileSize);
            //使用 StoreField 进行存储
            Field fieldSizeStore = new StoredField("size", fileSize);

            //对每个文件创建文本对象.
            Document document = new Document();
            ///4. 像文档中添加域
            document.add(fieldName);
            document.add(fieldPath);
            document.add(fieldContent);
            //添加的时候也要把这两个都添加进去
            document.add(fieldSizeValue);
            document.add(fieldSizeStore);
            //5. 把文档对象写入索引库
            indexWriter.addDocument(document);
        }
        //6. 关闭 indexwriter
        indexWriter.close(); 
    }

3. 索引库的增加

添加索引到已存在的索引库

//添加索引
@Test
public void addDocument() throws Exception {
    //索引库存放路径
    Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
    IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
    //创建一个indexwriter对象
    IndexWriter indexWriter = new IndexWriter(directory, config);
    //创建一个Document对象
    Document document = new Document();
    //向document对象中添加域。
    //不同的document可以有不同的域,同一个document可以有相同的域。
    document.add(new TextField("filename", "新添加的文档", Field.Store.YES));
    document.add(new TextField("content", "新添加的文档的内容", Field.Store.NO));
    //LongPoint创建索引
    document.add(new LongPoint("size", 1000l));
    //StoreField存储数据
    document.add(new StoredField("size", 1000l));
    //不需要创建索引的就使用StoreField存储
    document.add(new StoredField("path", "d:/temp/1.txt"));
    //添加文档到索引库
    indexWriter.addDocument(document);
    //关闭indexwriter
    indexWriter.close();
}

4. 索引库的删除

删除全部
将索引目录的索引信息全部删除,直接彻底删除,无法恢复, 慎用.

    @Test
    public void deleteAllDocument() throws Exception 
        //索引库存放路径
        Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
        IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
        //创建一个indexwriter对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        indexWriter.deleteAll();
        indexWriter.close();
    }

指定查询条件删除
例如: 删除域名为 name 中,关键词为 apache 的文档

    @Test
    public void deleteDocument() throws Exception 
        //索引库存放路径
        Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
        IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
        //创建一个indexwriter对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        indexWriter.deleteDocuments(new Term("name","apache"));
        indexWriter.close();
    }

5. 索引库的修改

  • 索引库修改的原理就是先删除再新增一个.
  • 修改功能会根据 Term 进行匹配, 所有匹配到的都会被删除. 例如订单 ID,证件号等. 所以我们一般修改的时候, 都会根据一个唯一不重复的字段进行匹配修改. 但是使用 Term ,要求值必须是字符串, 如果不是,则无法使用 Term.
    @Test
    public void updateIndex() throws Exception 
        //索引库存放路径
        Directory directory = FSDirectory.open(new File("/Users/yzhang/Desktop/Director").toPath());
        IndexWriterConfig config = new IndexWriterConfig(new IKAnalyzer());
        //创建一个indexwriter对象
        IndexWriter indexWriter = new IndexWriter(directory, config);
        //创建一个Document对象
        Document document = new Document();
        document.add(new StringField("name", "zz",Field.Store.YES));
        document.add(new TextField("name", "zz1",Field.Store.YES));
        document.add(new TextField("name", "zz2",Field.Store.YES));

        //更新name 域中 值为 spring 的文档,为新的 Document
        indexWriter.updateDocument(new Term("name","spring"), document);
        indexWriter.close();
    }

下一章重点学习一下查询, Lucene 的查询是很重要的. 所以单独用一个章节来学习.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容