0
点赞
收藏
分享

微信扫一扫

lucene建立索引的API导读

package org.apache.lucene.demo;

 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */

 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.NumericField;
 import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.index.IndexWriterConfig.OpenMode;
 import org.apache.lucene.index.IndexWriterConfig;
 import org.apache.lucene.index.Term;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.store.FSDirectory;
 import org.apache.lucene.util.Version;

 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.util.Date;

 /** Index all text files under a directory. See http://lucene.apache.org/java/3_1/demo.html. */
 public class IndexFiles {
   
   private IndexFiles() {}

   /** Index all text files under a directory. 
    * mian==>>args的数组是通过cmd窗口传进来的,
    * 所以每一个参数在下面的代码中相应的解析和作用
    */
   public static void main(String[] args) {
      
     /**
      * Help的帮助信息,如果程序的时候,没有设置相关相信,那么这个usage字符串就会打印到控制台去
      */  
     String usage = "java org.apache.lucene.demo.IndexFiles"
                  + " [-index INDEX_PATH] [-docs DOCS_PATH] [-update]\n\n"
                    // TODO: Change the link with every release (or: fill in some less error-prone alternative here...)
                  + "See http://lucene.apache.org/java/3_1/demo.html for details.";
     
     String indexPath = "index"; //创建索引的路径
     String docsPath = null;     //初始文档的路径
     boolean create = true;      //creat表示:如果已经有所以了,true表示重新建一个,
                                 //false表示如果有,那么我不需要重新建索引,没有的话我重新建一个索引
     /**
      * 对main的数组参数进行分析
      * 每一个输入的符号都占有一个位置,根据位子的标号,赋值相对应的值
      */
     for(int i=0;i<args.length;i++) { //for循环,取得args的长度,这样可以对数组里面的值进行充分的解析和赋值
         
          //每一次循环都会判断这个if,如果出现的args[i] 中的位置上匹配到-index,
          //那么i的下一个位子就是我们要的设置的索引的位子,我们将它设置为indexPath 
       if ("-index".equals(args[i])) {
           
         indexPath = args[i+1]; //将外界设定的索引的位子赋值给indexPath的程序代码中去
         i++;                   //i++ 表示下一轮的值,我们不需要增加一,因为下一个的值args[i+1]
                                //已经被赋值给了indexPath了
       } 
       //同样道理了,这里是取得的是文本docs的路径了,就是我们要寻找资料的那些原始文本信息放在这个路径下面了
       //通过匹配到 -docs 这个值,我们将-docs这个值的位子的后面一位的值赋值给docsPath这个参数变量
       //那么程序就得到了这个参数
       else if ("-docs".equals(args[i])) { 
         docsPath = args[i+1]; //思路和indexPath一样
          i++;                 //思路和indexPath一样
       } 
       //这个就是设定如果不是第一次启动的,我设置创建索引的是怎样的
       //updata是升级更新的意思,如果外界输入的updata那么我们匹配为false,
       //否则我们默认的值是true了
       else if ("-update".equals(args[i])) {
         create = false;
       }
     } //end for 

     //***********************************************************************************
     //****以上demo的从cmd启动以后程序才能启动,那么如果我们要从程序中启动,那么怎么办
     //其实很简单的,那么我们覆盖掉从外面设定的参数就可以了,如果从程序中启动,那么相当于args的数组的值是0
     //也就是说了,for循环将不会被执行的,我们要执行那么要代码方式的配置索引以及文本信息的路径了
     //相关的索引的路径以及原始的文本路径将不会被设置,我们可以这这里设置啊
     //**********************************************************************************
     //demo的程序启动要需要的配置在这里
     //_________________________________________________________________________________
     
     //代码方式的设置索引的路径
     indexPath = "D:\\lucene_workspace\\Lucene32Demo\\test-files\\indexFiles" ; //设置索引的路径
     docsPath  = "D:\\lucene_workspace\\Lucene32Demo\\test-files\\docs" ; //设置文本的路径
     create    = false ; //设置索引是否需要重新见过,默认是需要的True
     //___________________________________________________________________________________
     
     //这里是打印帮助信息了
     //首先判断的是docsPath是不是为空
     //如果为空,那么打印帮助信息,帮助信息的设置是在main的开始已经被设置好了的
     if (docsPath == null) {
       System.err.println("Usage: " + usage); //打印帮助信息
       System.exit(1);                        //并且退出jvm
     }
     
     //如果docsPath不为空,那么会执行这里,定义相关的信息
     final File docDir = new File(docsPath); //定义了一个final类型的File类型,就是放文本信息的文件夹
     //有需要进行判断,我通过file名字docDir去判断
     //如果我的文件夹是没有的或者不能被只读,那么相当于这个是没有用
     //所以会执行文件夹不存在或者不能背读取,请检查
     if (!docDir.exists() || !docDir.canRead()) {
       System.out.println("Document directory '" +docDir.getAbsolutePath()+ "' does not exist or is not readable, please check the path");
       System.exit(1);  //并且退出了虚拟机
     }
     
     Date start = new Date();  //这里定义了了一个日期,作用的话要过户下面用到
     
     try {
       System.out.println("Indexing to directory '" + indexPath + "'..."); //打印出所以的路径位子
       
        //这里是创建了一个Directory的变量,存放的是索引库
       Directory dir = FSDirectory.open(new File(indexPath));              
      
       //这里是创建了一个分词器标准的分词器,并且版本是version31的,lucene32应该也支持这个版本的
       //一般对中文的支持不好,所以我们第一次进行学习的时候用默认的demo文本
       //如果有其他支持中文的分词器,并且兼容到lucene的接口,那么可以在这里设置
       Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_31);       
       
       //这里是配置对索引的操作的配置器,并不是进行文本的搜索的配置
       //网上的资料上应该有些是一些对索引表的操作,比如更新,删除以及增加
       IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_31, analyzer);
       
      //这里是判断我创建的索引表的时候,是不是要重新创建还是不需要重新创建
       if (create) {
         // Create a new index in the directory, removing any 创建一个新的索引表,
         // previously indexed documents:并且删除掉当前以及存在的索引表
         iwc.setOpenMode(OpenMode.CREATE);    //设置配置属性,将创建索引表的配置值该为OpenMode.CREATE
       } else {
         // Add new documents to an existing index:
         //如果是false,那么就需要重新创建聊
         iwc.setOpenMode(OpenMode.CREATE_OR_APPEND); //这里是如果没有,那么我重新创建,如果有那么不创建
       }

       // Optional: for better indexing performance, if you
       // are indexing many documents, increase the RAM
       // buffer.  But if you do this, increase the max heap
       // size to the JVM (eg add -Xmx512m or -Xmx1g):
       //如果你的索引文件有好多,为了有更好的效果比如速度啊,那么需要增加JVM的内存堆内存
       //什么是对内存,堆内存是存放class文件对象的以及一些数组啊
       // iwc.setRAMBufferSizeMB(256.0);
       
       //设置好索引配置器以后,设定索引操作器,索引操作器就是要传入索引配置器以及索引库
       //这样才能有目标对索引进行操作
       IndexWriter writer = new IndexWriter(dir, iwc);
      
       
       //这个是方法,静态方法,在下面给出来的下面我们去那分析吧=========》》》》
       //******************************************************************************************
       indexDocs(writer, docDir);
       //******************************************************************************************
       
      
       // NOTE: if you want to maximize search performance,
       // you can optionally call optimize here.  This can be
       // a costly operation, so generally it's only worth
       // it when your index is relatively static (ie you're
       // done adding documents to it):
       //这里有说明,如果你想最大话搜索的性能,那么你可以选择进行优化索引器,
       //就是设置一个参数喽
       // writer.optimize();
       //关闭索引器让JVM回收内存,底层操作应该涉及到文件的IO的吧,我没看过,应该是这样的
       //因为和文件操作有关系吧
       writer.close();
   
       Date end = new Date(); //设定结束时间,哦了,这个就是设置用的,来取得一个操作的需要花费的时间
       System.out.println(end.getTime() - start.getTime() + " total milliseconds");

     } catch (IOException e) {
     
     //抛异常,我勒个去的,你累不累啊,还要写实哪个类的哪个异常,不过这样的写法还是值得学习的
       System.out.println(" caught a " + e.getClass() +
        "\n with message: " + e.getMessage());
     }
   }

   
   /**
    * Indexes the given file using the given writer, or if a directory is given,
    * recurses over files and directories found under the given directory.
    * 
    * NOTE: This method indexes one document per input file.  This is slow.  For good
    * throughput, put multiple documents into your input file(s).  An example of this is
    * in the benchmark module, which can create "line doc" files, one document per line,
    * using the
    * <a href="../../../../../contrib-benchmark/org/apache/lucene/benchmark/byTask/tasks/WriteLineDocTask.html"
    * >WriteLineDocTask</a>.
    *  
    * @param writer Writer to the index where the given file/dir info will be stored
    * @param file The file to index, or the directory to recurse into to find files to index
    * @throws IOException
    */
   /**
    * 输入的是操作索引的IndexWtriter
    * 输入的是文件,这些文件要有索引操作器,会转换成一些索引表,而这么文件就成了索引数据,真一个加起来就是索引库
    */
   static void indexDocs(IndexWriter writer, File file)
     throws IOException {
     // do not try to index files that cannot be read
     //不要将索引文件设置成为不可读甚至是不可写,就是普通的可读可写类型
     if (file.canRead()) { //判断文件是否可读,如果文件可读那么执行
         
       if (file.isDirectory()) { //判断文件是不是是一个文件夹,文件夹里面有好多个文本信息 
         String[] files = file.list(); //如果是文件,那么将文件中的文本列入到一个string类型的数组中,这个操作应该是将文本的文本名字
         // an IO error could occur 如果发生了一个文件读写的错误
         if (files != null) { //如果这个数组是不为空,也就是说,文件夹中有文本信息存在的
           for (int i = 0; i < files.length; i++) { //做一个for循环,取得string数组的长度,有多少个文件
               
             indexDocs(writer, new File(file, files[i])); //递归操作 ?? 这个应该是吧
             
           } // end for
         } // end if
       } //end if
       
       //如果不是能被读取的
       else {
         FileInputStream fis;
         try {
           fis = new FileInputStream(file);
         } catch (FileNotFoundException fnfe) {
           // at least on windows, some temporary files raise this exception with an "access denied" message
           // checking if the file can be read doesn't help
           return;
         }

         try {

           // make a new, empty document
           Document doc = new Document(); //创建一个空的文档,就是索引信息了

           // Add the path of the file as a field named "path".  Use a
           // field that is indexed (i.e. searchable), but don't tokenize 
           // the field into separate words and don't index term frequency
           // or positional information:
           
           //字段设置,可以设置多个的,用key-value的方式,
           //一共四个参数
           //1.设定是的索引的信息名相当于key
           //2.设定的是索引的信息值相当于value
           //3.设定的是索引的是不是要保存啊 这个再看资料
           //4.这个当然是字段的索引的参数设置了,要不你再查查API O(∩_∩)O哈哈~
           Field pathField = new Field("path", file.getPath(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
           pathField.setOmitTermFreqAndPositions(true);
           doc.add(pathField);
           
           //自己添加一个试试看
           Field mypathField = new Field("name", file.getName(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS);
           mypathField.setOmitTermFreqAndPositions(true);
           doc.add(mypathField);

           // Add the last modified date of the file a field named "modified".
           // Use a NumericField that is indexed (i.e. efficiently filterable with
           // NumericRangeFilter).  This indexes to milli-second resolution, which
           // is often too fine.  You could instead create a number based on
           // year/month/day/hour/minutes/seconds, down the resolution you require.
           // For example the long value 2011021714 would mean
           // February 17, 2011, 2-3 PM.
           NumericField modifiedField = new NumericField("modified");
           modifiedField.setLongValue(file.lastModified());
           doc.add(modifiedField);

           // Add the contents of the file to a field named "contents".  Specify a Reader,
           // so that the text of the file is tokenized and indexed, but not stored.
           // Note that FileReader expects the file to be in UTF-8 encoding.
           // If that's not the case searching for special characters will fail.
           doc.add(new Field("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));

           if (writer.getConfig().getOpenMode() == OpenMode.CREATE) {
             // New index, so we just add the document (no old document can be there):
             System.out.println("adding " + file);
             writer.addDocument(doc);
           } else {
             // Existing index (an old copy of this document may have been indexed) so 
             // we use updateDocument instead to replace the old one matching the exact 
             // path, if present:
             System.out.println("updating " + file);
             writer.updateDocument(new Term("path", file.getPath()), doc);
           }
           
         } finally {
           fis.close();
         }
       }
     }
   }
 }

举报

相关推荐

07Lucene索引库的修改

0 条评论