美文网首页
Lucene 入门 06 - 索引库的维护

Lucene 入门 06 - 索引库的维护

作者: __Y_Q | 来源:发表于2020-01-16 15:29 被阅读0次

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

    在前几章说过了创建索引库, 但是在创建 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 的查询是很重要的. 所以单独用一个章节来学习.

    相关文章

      网友评论

          本文标题:Lucene 入门 06 - 索引库的维护

          本文链接:https://www.haomeiwen.com/subject/xtyczctx.html