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
  • 相关阅读:
    tensorflow 2.0 学习 (十) 拟合与过拟合问题
    tensorflow 2.0 学习 (九) tensorboard可视化功能认识
    tensorflow 2.0 学习 (八) keras模块的认识
    tensorflow 2.0 学习 (七) 反向传播代码逐步实现
    tensorflow 2.0 学习 (六) Himmelblua函数求极值
    tensorflow 2.0 学习 (五)MPG全连接网络训练与测试
    arp协议简单介绍
    Pthread spinlock自旋锁
    线程和进程状态
    内核态(内核空间)和用户态(用户空间)的区别和联系·
  • 原文地址:https://www.cnblogs.com/amosli/p/3976246.html
Copyright © 2011-2022 走看看