zoukankan      html  css  js  c++  java
  • 搜索引擎系列 ---lucene简介 创建索引和搜索初步

     一、什么是Lucene?

    Lucene最初是由Doug Cutting开发的,2000年3月,发布第一个版本,是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎 ;Lucene得名于Doug妻子的中名,同时这也她外祖母的姓;目前是Apache基金会的一个顶级项目,同时也是学习搜索引擎入门必知必会。

    Lucene 是一个 JAVA 搜索类库,它本身并不是一个完整的解决方案,需要额外的开发工作。

    优点:成熟的解决方案,有很多的成功案例。apache 顶级项目,正在持续快速的进步。庞大而活跃的开发社区,大量的开发人员。它只是一个类库,有足够的定制和优化空间:经过简单定制,就可以满足绝大部分常见的需求;经过优化,可以支持 10亿+ 量级的搜索。

    缺点:需要额外的开发工作。所有的扩展,分布式,可靠性等都需要自己实现;非实时,从建索引到可以搜索中间有一个时间延迟,而当前的“近实时”(Lucene Near Real Time search)搜索方案的可扩展性有待进一步完善。

    对于全文检索一般都由以下3个部分组成:

    • 索引部分
    • 分词部分
    • 搜索部分

    在接下来的一系列文章中会详细介绍这三个部分,本文将简单介绍lucene环境搭建以及lucene索引初步。

    目前基于Lucene的产品有:

    Solr,Nutch,Hbase,Katta,constellio,Summa,Compass,Bobo Search,Index Tank,Elastic Search,Hadoop contrib/index ,LinkedIn ,Eclipse,Cocoon

    二、Lucene环境搭建

    目录最新版的Lucene为4.10.0(今天是2014-09-22 )版,其官方主页为:http://lucene.apache.org/ 

    或者点击下载

    如果你会使用Maven,那么可以非常简单的将pom.xml中加入以下内容即可:

        <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-core</artifactId>
                <version>4.10.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-analyzers-common</artifactId>
                <version>4.10.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-queryparser</artifactId>
                <version>4.10.0</version>
            </dependency>

    如果不会使用Maven,则需要手工下载相应的jar包进行开发。

    三、索引创建

    1、创建Directory

    2、创建IndexWriter

    3、创建Document对象

    4、为Docuemnt添加Field

    5、通过IndexWriter添加文档到Document

    package com.amos.lucene;
    
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.document.Field;
    import org.apache.lucene.document.FieldType;
    import org.apache.lucene.document.TextField;
    import org.apache.lucene.index.IndexWriter;
    import org.apache.lucene.index.IndexWriterConfig;
    import org.apache.lucene.index.IndexableField;
    import org.apache.lucene.index.IndexableFieldType;
    import org.apache.lucene.store.FSDirectory;
    import org.apache.lucene.store.RAMDirectory;
    import org.apache.lucene.util.Version;
    
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    
    /**
     * Created by amosli on 14-9-17.
     */
    public class HelloLucene {
       static String indexDir = "/home/amosli/developtest/lucene";
    
        public void index() {
            IndexWriter indexWriter = null;
            FSDirectory directory = null;
            try {
                //1、创建Directory
                 directory = FSDirectory.open(new File(indexDir));
                //RAMDirectory directory = new RAMDirectory();
    
                //2、创建IndexWriter
                IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_4_10_0, new StandardAnalyzer(Version.LUCENE_4_10_0));
                indexWriter = new IndexWriter(directory, indexWriterConfig);
    
                File file = new File("/home/amosli/developtest/testfile");
                for (File f : file.listFiles()) {
    
                    FieldType fieldType = new FieldType();
                    //3、创建Docuemnt对象
                    Document document = new Document();
    
                    //4、为Document添加Field
                    document.add(new TextField("content", new FileReader(f)) );
    
                    fieldType.setIndexed(true);
                    fieldType.setStored(true);
                    document.add(new Field("name", f.getName(),fieldType));
    
                    fieldType.setIndexed(false);
                    fieldType.setStored(true);
                    document.add(new Field("path", f.getAbsolutePath(), fieldType));
    
                    //5、通过IndexWriter添加文档索引中
                    indexWriter.addDocument(document);
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (indexWriter != null) {
                    try {
                        indexWriter.close();
    
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }

    注:

      1、这里使用的是FSDirectory,是为了方便进行测试,将生成的文件写入到本地硬盘中;

           2、Document相当于数据库中的一条记录,field相当数据库中表的一列;

           3、使用indexWriter当记录添加到文档索引中;

           4、fieldType可以设置是否需要索引和是否需要存储;

           5、记得关闭indexWriter

    生成的索引文件,如下图所示:

    四、搜索记录

    1、创建Directory

    2、创建IndexReader

    3、根据IndexReader创建IndexSearcher

    4、创建搜索的Query

    5、根据Searcher搜索并且返回TopDocs

    6、根据TopDocs获取ScoreDoc对象

    7、根据Seacher和ScoreDoc对象获取具体的Document对象

    8、根据Document对象获取需要的值

     public void search() {
            IndexReader indexReader = null;
            try {
                //1、创建Directory
                FSDirectory directory = FSDirectory.open(new File(indexDir));
    
                //2、创建IndexReader
                 indexReader = DirectoryReader.open(directory);
    
                //3、根据IndexReader创建IndexSearcher
                IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    
                //4、创建搜索的Query
                //创建querypaser来确定要搜索文件的内容,第二个参数表示搜索的域
                QueryParser queryParser = new QueryParser("content", new StandardAnalyzer());
                //创建query,表示搜索域为content中包含java的文档
                Query query = queryParser.parse("java");
                //5、根据Searcher搜索并且返回TopDocs
                TopDocs topDocs = indexSearcher.search(query, 100);
                //6、根据TopDocs获取ScoreDoc对象
                ScoreDoc[] sds = topDocs.scoreDocs;
                //7、根据Seacher和ScoreDoc对象获取具体的Document对象
                for (ScoreDoc sdc : sds) {
                    Document doc = indexSearcher.doc(sdc.doc);
                    //8、根据Document对象获取需要的值
                    System.out.println("name:" + doc.get("name") + "----->  path:" + doc.get("path"));
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }finally{
    
                if(indexReader!=null){
                    try {
                        indexReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

    输出结果:

    所有源码:HelloLucene.java 

    package com.amos.lucene;
    
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.document.Field;
    import org.apache.lucene.document.FieldType;
    import org.apache.lucene.document.TextField;
    import org.apache.lucene.index.*;
    import org.apache.lucene.queryparser.classic.ParseException;
    import org.apache.lucene.queryparser.classic.QueryParser;
    import org.apache.lucene.search.IndexSearcher;
    import org.apache.lucene.search.Query;
    import org.apache.lucene.search.ScoreDoc;
    import org.apache.lucene.search.TopDocs;
    import org.apache.lucene.store.FSDirectory;
    import org.apache.lucene.store.RAMDirectory;
    import org.apache.lucene.util.Version;
    
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    
    /**
     * Created by amosli on 14-9-17.
     */
    public class HelloLucene {
        static String indexDir = "/home/amosli/developtest/lucene";
    
        public void index() {
            IndexWriter indexWriter = null;
            FSDirectory directory = null;
            try {
                //1、创建Directory
                directory = FSDirectory.open(new File(indexDir));
                //RAMDirectory directory = new RAMDirectory();
    
                //2、创建IndexWriter
                IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_4_10_0, new StandardAnalyzer(Version.LUCENE_4_10_0));
                indexWriter = new IndexWriter(directory, indexWriterConfig);
    
                File file = new File("/home/amosli/developtest/testfile");
                for (File f : file.listFiles()) {
    
                    FieldType fieldType = new FieldType();
                    //3、创建Docuemnt对象
                    Document document = new Document();
    
                    //4、为Document添加Field
                    document.add(new TextField("content", new FileReader(f)));
    
                    fieldType.setIndexed(true);
                    fieldType.setStored(true);
                    document.add(new Field("name", f.getName(), fieldType));
    
                    fieldType.setIndexed(false);
                    fieldType.setStored(true);
                    document.add(new Field("path", f.getAbsolutePath(), fieldType));
    
                    //5、通过IndexWriter添加文档索引中
                    indexWriter.addDocument(document);
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (indexWriter != null) {
                    try {
                        indexWriter.close();
    
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        public void search() {
            IndexReader indexReader = null;
            try {
                //1、创建Directory
                FSDirectory directory = FSDirectory.open(new File(indexDir));
    
                //2、创建IndexReader
                 indexReader = DirectoryReader.open(directory);
    
                //3、根据IndexReader创建IndexSearcher
                IndexSearcher indexSearcher = new IndexSearcher(indexReader);
    
                //4、创建搜索的Query
                //创建querypaser来确定要搜索文件的内容,第二个参数表示搜索的域
                QueryParser queryParser = new QueryParser("content", new StandardAnalyzer());
                //创建query,表示搜索域为content中包含java的文档
                Query query = queryParser.parse("java");
                //5、根据Searcher搜索并且返回TopDocs
                TopDocs topDocs = indexSearcher.search(query, 100);
                //6、根据TopDocs获取ScoreDoc对象
                ScoreDoc[] sds = topDocs.scoreDocs;
                //7、根据Seacher和ScoreDoc对象获取具体的Document对象
                for (ScoreDoc sdc : sds) {
                    Document doc = indexSearcher.doc(sdc.doc);
                    //8、根据Document对象获取需要的值
                    System.out.println("name:" + doc.get("name") + "----->  path:" + doc.get("path"));
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }finally{
    
                if(indexReader!=null){
                    try {
                        indexReader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    }
    View Code

    TestHelloLucene.java

    package com.amos.lucene;
    
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.queryparser.classic.QueryParser;
    import org.junit.Test;
    
    /**
     * Created by amosli on 14-9-17.
     */
    public class TestHelloLucene {
        @Test
        public void testIndex(){
            HelloLucene helloLucene = new HelloLucene();
            helloLucene.index();
        }
        @Test
        public void testSearch(){
            HelloLucene helloLucene = new HelloLucene();
            helloLucene.search();
        }
    }
    View Code
  • 相关阅读:
    IE 8兼容:<meta http-equiv="X-UA-Compatible" content="IE=edge" /> X-UA-Compatible的解释
    点击下载,下载图片
    修改输入框placeholder文字默认颜色-webkit-input-placeholder
    rest_framework目录
    Django目录
    python基础内容目录
    hadoop伪分布式搭建
    通过ldap验证svn服务
    LDAP目录服务
    Python基础之字符串拼接简单介绍
  • 原文地址:https://www.cnblogs.com/amosli/p/3976246.html
Copyright © 2011-2022 走看看