zoukankan      html  css  js  c++  java
  • Lucene 4.7 学习及实例demo

      很早就听说Lucene的大名了,但一直没空研究,今天抽了一个下午时间,学习了一下Lucene,写了一个简单的Demo,总的感受是使用起来简单方便,在使用之前,首先要理解以下关键的类:

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

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

    Analyzer 
    在一个文档被索引之前,首先需要对文档内容进行分词处理,这部分工作就是由 Analyzer 来做的。Analyzer 类是一个抽象类,它有多个实现。针对不同的语言和应用需要选择适合的 Analyzer。Analyzer 把分词后的内容交给 IndexWriter 来建立索引。 

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

    Directory 
    这个类代表了 Lucene 的索引的存储的位置,这是一个抽象类,它目前有两个实现,第一个是 FSDirectory,它表示一个存储在文件系统中的索引的位置。第二个是 RAMDirectory,它表示一个存储在内存当中的索引的位置。 

    Query 
    这是一个抽象类,他有多个实现,比如 TermQuery, BooleanQuery, PrefixQuery. 这个类的目的是把用户输入的查询字符串封装成 Lucene 能够识别的 Query。 

    IndexSearcher 
    IndexSearcher 是用来在建立好的索引上进行搜索的。它只能以只读的方式打开一个索引,所以可以有多个 IndexSearcher 的实例在一个索引上进行操作。

    Hits 
    Hits 是用来保存搜索结果的。 

    理解了这些类之后,我写了一个简单的demo,包括索引构建和索引搜索,以后如果要做复杂的搜索,可以根据这个demo做扩展,是不是很简单哈。

      1 import java.io.File;
      2 import java.io.IOException;
      3 import java.util.ArrayList;
      4 import java.util.List;
      5 import org.apache.lucene.analysis.Analyzer;
      6 import org.apache.lucene.analysis.standard.StandardAnalyzer;
      7 import org.apache.lucene.document.Document;
      8 import org.apache.lucene.document.Field;
      9 import org.apache.lucene.document.TextField;
     10 import org.apache.lucene.index.DirectoryReader;
     11 import org.apache.lucene.index.IndexWriter;
     12 import org.apache.lucene.index.IndexWriterConfig;
     13 import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
     14 import org.apache.lucene.search.IndexSearcher;
     15 import org.apache.lucene.search.Query;
     16 import org.apache.lucene.search.ScoreDoc;
     17 import org.apache.lucene.store.Directory;
     18 import org.apache.lucene.store.FSDirectory;
     19 import org.apache.lucene.util.Version;
     20 
     21 /**
     22  * Lucene Demo
     23  * Author: herui
     24  * DateTime: 2014-3-31 下午3:39:54
     25  */
     26 public class LuceneDemo {
     27     
     28     /**
     29      * 根据内容,构建索引
     30      * @param analyzer
     31      * @param directory
     32      * @param items
     33      * @return
     34      */
     35     private boolean buildIndexer(Analyzer analyzer, Directory directory, List<Item> items) {
     36         IndexWriter iwriter = null;
     37         try {
     38             // 配置索引
     39             iwriter = new IndexWriter(directory, new IndexWriterConfig(
     40                     Version.LUCENE_47, analyzer));
     41             // 删除所有document
     42             iwriter.deleteAll();
     43             // 将文档信息存入索引
     44             Document doc[] = new Document[items.size()];
     45             for (int i = 0; i < items.size(); i++) {
     46                 doc[i] = new Document();
     47                 
     48                 Item item = items.get(i);
     49                 java.lang.reflect.Field[] fields = item.getClass().getDeclaredFields();
     50                 for (java.lang.reflect.Field field : fields) {
     51                     String fieldName = field.getName();
     52                     String getMethodName = "get"+toFirstLetterUpperCase(fieldName);
     53                     Object obj = item.getClass().getMethod(getMethodName).invoke(item);
     54                     doc[i].add(new Field(fieldName, (String)obj, TextField.TYPE_STORED));
     55                 }
     56                 
     57                 iwriter.addDocument(doc[i]);
     58             }
     59         } catch (Exception e) {
     60             e.printStackTrace();
     61             return false;
     62         } finally {
     63             try {
     64                 iwriter.close();
     65             } catch (IOException e) {
     66             }
     67         }
     68         return true;
     69     }
     70     
     71     /**
     72      * 根据keyword搜索索引
     73      * @param analyzer
     74      * @param directory
     75      * @param keyword
     76      * @return
     77      */
     78     public List<Item> searchIndexer(Analyzer analyzer, Directory directory, String keyword) {
     79         DirectoryReader ireader = null;
     80         List<Item> result = new ArrayList<Item>();
     81         try {
     82             // 设定搜索目录
     83             ireader = DirectoryReader.open(directory);
     84             IndexSearcher isearcher = new IndexSearcher(ireader);
     85 
     86             // 对多field进行搜索
     87             java.lang.reflect.Field[] fields = Item.class.getDeclaredFields();
     88             int length = fields.length;
     89             String[] multiFields = new String[length];
     90             for (int i = 0; i < length; i++) {
     91                 multiFields[i] = fields[i].getName();
     92             }
     93             MultiFieldQueryParser parser = new MultiFieldQueryParser(
     94                     Version.LUCENE_47, multiFields, analyzer);
     95 
     96             // 设定具体的搜索词
     97             Query query = parser.parse(keyword);
     98             ScoreDoc[] hits = isearcher.search(query, null, 10).scoreDocs;
     99 
    100             for (int i = 0; i < hits.length; i++) {
    101                 Document hitDoc = isearcher.doc(hits[i].doc);
    102                 Item item = new Item();
    103                 for (String field : multiFields) {
    104                     String setMethodName = "set"+toFirstLetterUpperCase(field);
    105                     item.getClass().getMethod(setMethodName, String.class).invoke(item, hitDoc.get(field));
    106                 }
    107                 result.add(item);
    108             }
    109         } catch (Exception e) {
    110             e.printStackTrace();
    111             return null;
    112         } finally {
    113             try {
    114                 ireader.close();
    115                 directory.close();
    116             } catch (IOException e) {
    117             }
    118         }
    119         return result;
    120     }
    121     
    122     /**
    123      * 首字母转大写
    124      * @param str
    125      * @return
    126      */
    127     public static String toFirstLetterUpperCase(String str) {  
    128         if(str == null || str.length() < 2){  
    129             return str;  
    130         }  
    131         return str.substring(0, 1).toUpperCase() + str.substring(1, str.length());  
    132      }  
    133     
    134     public static void main(String[] args) throws Exception {
    135         LuceneDemo demo = new LuceneDemo();
    136         Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_47);
    137         
    138         List<Item> items = new ArrayList<Item>();
    139         items.add(new Item("1", "first", "This is the text to be greatly indexed."));
    140         items.add(new Item("2", "second", "This is great"));
    141         items.add(new Item("3", "third", "I love apple and pear. "));
    142         items.add(new Item("4", "four", "我是中国人"));
    143         items.add(new Item("5", "five", "我叫何瑞"));
    144         
    145         // 索引存到内存中的目录
    146         //Directory directory = new RAMDirectory();
    147         // 索引存储到硬盘
    148         File file = new File("d:/lucene");
    149         Directory directory = FSDirectory.open(file);
    150         demo.buildIndexer(analyzer, directory, items);
    151         List<Item> result = demo.searchIndexer(analyzer, directory, "中国");
    152         
    153         for (Item item : result) {
    154             System.out.println(item.toString());
    155         }
    156     }
    157 }

    Item.java

     1 public class Item {
     2     
     3     private String id;
     4     private String title;
     5     private String content;
     6     
     7     public Item() {
     8     }
     9     
    10     public Item(String id, String title, String content) {
    11         this.id = id;
    12         this.title = title;
    13         this.content = content;
    14     }
    15     
    16     public String getId() {
    17         return id;
    18     }
    19     public void setId(String id) {
    20         this.id = id;
    21     }
    22     public String getTitle() {
    23         return title;
    24     }
    25     public void setTitle(String title) {
    26         this.title = title;
    27     }
    28     public String getContent() {
    29         return content;
    30     }
    31     public void setContent(String content) {
    32         this.content = content;
    33     }
    34     
    35     public String toString() {
    36         StringBuilder sb = new StringBuilder();
    37         sb.append("[id=").append(id).append(",title=").append(title)
    38             .append(",content=").append(content).append("]");
    39         return sb.toString();
    40     }
    41 }
  • 相关阅读:
    ACM解题之快速输出杨辉三角形(前68行)
    ACM解题之素矩阵
    ACM解题之回文序列
    python批量修改文件名
    HTML页面导航栏页脚不动,变换中间部分
    VS2013正则表达式应用示例
    <<数学传奇>>概述
    C#在不同平台下DLL的引用问题
    在C++中实现类似Java的“synchronized”
    VS编译完成后自动复制到远程机器
  • 原文地址:https://www.cnblogs.com/herui/p/3636192.html
Copyright © 2011-2022 走看看