zoukankan      html  css  js  c++  java
  • 1. 初识 Lucene

    在学习Lucene之前呢,我们当然首先要了解下什么是Lucene.

    0x01 什么是Lucene ?

    Lucene是一套用于全文检索和搜索的开放源代码程序库,由Apache软件基金会支持和提供。

    Lucene提供了一个简单却强大的应用程序接口,能够做全文索引和搜索,在Java开发环境里Lucene是一个成熟的免费开放源代码工具;

    就其本身而论,Lucene是现在并且是这几年,最受欢迎的免费Java信息检索程序库。

    Lucene最初是由Doug Cutting所撰写的,他贡献出Lucene的目标是为各种中小型应用程序加入全文检索功能

    Tips: 摘要来自维基百科 https://zh.wikipedia.org/wiki/Lucene

    这里我们只需要知道Lucene是目前最为流行的基于 Java 开源全文检索工具包。

    0x02 Lucene 是用来做什么的?

    基于Lucene的著名项目

    项目名称  项目描述
    Apache Nutch  提供成熟可用的网络爬虫
    Apache Solr   基于Lucenne核心的高性能搜索服务器,提供JSON/Python/Ruby API
    Elasticsearch   企业搜索平台,目的是组织数据并使其易于获取
    DocFetcher 跨平台的本机文件搜索桌面程序
    Lucene.NET  提供给.Net平台用户的Lucene类库的封装
    Swiftype 基于Lucene的企业级搜索
    Apache Lucy 为动态语言提供全文搜索的能力,是Lucene Java 库的C接口

     

    其实我们不难发现主要用途

    • 可以用来编写网络爬虫
    • 也可以用来实现网站后台的全文检索。

    偶然发现这张图感觉挺不错的,在这里分享下:

    搜索应用程序和 Lucene 之间的关系

    Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。

    0x03 Lucene 软件包分析

    Lucene 软件包的发布形式是一个 JAR 文件,下面我们分析一下这个 JAR 文件里面的主要的 JAVA 包,使读者对之有个初步的了解。

    Package: org.apache.lucene.document

    这个包提供了一些为封装要索引的文档所需要的类,比如 Document, Field。这样,每一个文档最终被封装成了一个 Document 对象。

    Package: org.apache.lucene.analysis

    这个包主要功能是对文档进行分词,因为文档在建立索引之前必须要进行分词,所以这个包的作用可以看成是为建立索引做准备工作。

    Package: org.apache.lucene.index

    这个包提供了一些类来协助创建索引以及对创建好的索引进行更新。这里面有两个基础的类:IndexWriter 和 IndexReader,

    其中 IndexWriter 是用来创建索引并添加文档到索引中的,IndexReader 是用来删除索引中的文档的。

    Package: org.apache.lucene.search

    这个包提供了对在建立好的索引上进行搜索所需要的类。比如 IndexSearcher 和 Hits, IndexSearcher 定义了在指定的索引上进行搜索的方法,Hits 用来保存搜索得到的结果。

    0x04 搭建Lucene 开发环境?

    相信你和我一样已经控制不住自己的洪荒之力想要写个demo来跑跑了,但是在此之前我们还是要先搭建好开发环境。

    1. 首先我们需要找到Lucene的官网

    Lucene官网:https://lucene.apache.org/

    翻译内容如下:

    Apache LuceneTM项目开发开源搜索软件,其中包括:

    我们的旗舰子项目Lucene Core提供了基于Java的索引和搜索技术,以及拼写检查,高亮显示和高级分析/标记化功能。
    SolrTM是一款使用Lucene Core构建的高性能搜索服务器,具有XML / HTTP和JSON / Python / Ruby API,高亮显示,多面搜索,缓存,复制和Web管理界面。
    PyLucene是Core项目的Python端口。

     2.点击上图中的Download 按钮,会跳转到这个下载页面

    Tips: 这里存在很多镜像下载链接,我们选择推荐的下载链接下载即可。

    0x05 Lucene Hello World Sample

    文档资料相信你在其他网站已经看了不少,但是不写一个能跑起来的Hello World 对于初学者来说是非常痛苦的。

    对于这个简单的例子,我们将从一些字符串中创建一个内存索引

    1.创建Maven 项目

    2.选择创建一个简单的Maven Project

    3. 配置工程信息

    4. 点击完成

    5. 配置POM.xml

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.xingyun</groupId>
      <artifactId>lucene-sample</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>jar</packaging>
      
      <name>lucene-sample</name>
       
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
        
        <build>
          <plugins>
              <plugin>
                  <groupId>org.codehaus.mojo</groupId>
                  <artifactId>exec-maven-plugin</artifactId>
                  <version>1.3.2</version>
                  <executions>
                      <execution>
                          <id>ex</id>
                          <phase>package</phase>
                          <goals>
                              <goal>exec</goal>
                          </goals>
                          <configuration>
                              <executable>java</executable>
                              <arguments>
                                  <argument>-classpath</argument>
                                  <classpath />
                                  <argument>HelloLucene.HelloLucene</argument>
                              </arguments>
                          </configuration>
                      </execution>
                  </executions>
              </plugin>
          </plugins>
        </build>
    
        <dependencies>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-core</artifactId>
                <version>4.0.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-queries</artifactId>
                <version>4.0.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-test-framework</artifactId>
                <version>4.0.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-analyzers-common</artifactId>
                <version>4.0.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.lucene</groupId>
                <artifactId>lucene-queryparser</artifactId>
                <version>4.0.0</version>
            </dependency>
        </dependencies>
    </project>

     6. 创建HelloLucene.java

    package com.xingyun;
    
    import java.io.IOException;
    import java.text.ParseException;
    
    import org.apache.lucene.analysis.standard.StandardAnalyzer;
    import org.apache.lucene.document.Document;
    import org.apache.lucene.document.Field;
    import org.apache.lucene.document.StringField;
    import org.apache.lucene.document.TextField;
    import org.apache.lucene.index.DirectoryReader;
    import org.apache.lucene.index.IndexReader;
    import org.apache.lucene.index.IndexWriter;
    import org.apache.lucene.index.IndexWriterConfig;
    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.TopScoreDocCollector;
    import org.apache.lucene.store.Directory;
    import org.apache.lucene.store.RAMDirectory;
    import org.apache.lucene.util.Version;
    
    public class HelloLucene {
    
        public static void main(String[] args) throws IOException, ParseException {
    
            // 对于这个简单的例子,我们将从一些字符串中创建一个内存索引。
            // 0. Specify the analyzer for tokenizing text.
            // The same analyzer should be used for indexing and searching
            StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_40);
    
            // 1. create the index
            Directory index = new RAMDirectory();
    
            IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_40, analyzer);
    
            IndexWriter w = new IndexWriter(index, config);
            addDoc(w, "Lucene in Action", "193398817");
            addDoc(w, "Lucene for Dummies", "55320055Z");
            addDoc(w, "Managing Gigabytes", "55063554A");
            addDoc(w, "The Art of Computer Science", "9900333X");
            w.close();
    
            // 2. query
            String querystr = args.length > 0 ? args[0] : "lucene";
    
            // the "title" arg specifies the default field to use
            // when no field is explicitly specified in the query.
            Query q = null;
            try {
                q = new QueryParser(Version.LUCENE_40, "title", analyzer).parse(querystr);
            } catch (org.apache.lucene.queryparser.classic.ParseException e) {
                e.printStackTrace();
            }
    
            // 3. search
            int hitsPerPage = 10;
            IndexReader reader = DirectoryReader.open(index);
            IndexSearcher searcher = new IndexSearcher(reader);
            TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
            searcher.search(q, collector);
            ScoreDoc[] hits = collector.topDocs().scoreDocs;
    
            // 4. display results
            System.out.println("Found " + hits.length + " hits.");
            for (int i = 0; i < hits.length; ++i) {
                int docId = hits[i].doc;
                Document d = searcher.doc(docId);
                System.out.println((i + 1) + ". " + d.get("isbn") + "	" + d.get("title"));
            }
    
            // reader can only be closed when there
            // is no need to access the documents any more.
            reader.close();
        }
    
        private static void addDoc(IndexWriter w, String title, String isbn) throws IOException {
            Document doc = new Document();
            doc.add(new TextField("title", title, Field.Store.YES));
    
            // use a string field for isbn because we don't want it tokenized
            doc.add(new StringField("isbn", isbn, Field.Store.YES));
            w.addDocument(doc);
        }
    
    }

    7. 运行后,我们便可以得到索引集合中带有Lucene的所有内容

    0x06  代码剖析

    我们运行成功后,相信此时的你已经有心情和我一起来分析代码了吧。

    1. 创建索引

    StandardAnalyzer analyzer = new StandardAnalyzer();
    Directory index = new RAMDirectory();
    
    IndexWriterConfig config = new IndexWriterConfig(analyzer);
    
    IndexWriter w = new IndexWriter(index, config);
    addDoc(w, "Lucene in Action", "193398817");
    addDoc(w, "Lucene for Dummies", "55320055Z");
    addDoc(w, "Managing Gigabytes", "55063554A");
    addDoc(w, "The Art of Computer Science", "9900333X");
    w.close();

    我们需要虚构一些假的数据,通过上面的方式来对一些字符串和数字创建索引

    addDoc 方法定义如下所示:

    private static void addDoc(IndexWriter w, String title, String isbn) throws IOException {
      Document doc = new Document();
      doc.add(new TextField("title", title, Field.Store.YES));
      doc.add(new StringField("isbn", isbn, Field.Store.YES));
      w.addDocument(doc);
    }

    2. 查询

    String querystr = args.length > 0 ? args[0] : "lucene";
    Query q = new QueryParser("title", analyzer).parse(querystr);

    3.搜索

    int hitsPerPage = 10;
    IndexReader reader = DirectoryReader.open(index);
    IndexSearcher searcher = new IndexSearcher(reader);
    TopDocs docs = searcher.search(q, hitsPerPage);
    ScoreDoc[] hits = docs.scoreDocs;

    4.显示结果

    System.out.println("Found " + hits.length + " hits.");
    for(int i=0;i<hits.length;++i) {
        int docId = hits[i].doc;
        Document d = searcher.doc(docId);
        System.out.println((i + 1) + ". " + d.get("isbn") + "	" + d.get("title"));
    }

    0x07 参考资料:

    Lucene in 5 minutes:http://www.lucenetutorial.com/lucene-in-5-minutes.html

    Lucene常识总结以及小demo总结  http://www.imooc.com/article/21946

    Lucene 概述: https://www.ibm.com/developerworks/cn/java/j-lo-lucene1/

    视频实战教程:

    基于Lucene4.6+Solr4.6+Heritrix1.14+S2SH实战开发从无到有垂直搜索引擎

    网盘地址: 密码: 9ang

    备用地址(腾讯微云): 密码:p8TmhQ

  • 相关阅读:
    day4递归原理及实现
    day4装饰器
    day4迭代器&生成器&正则表达式
    open()函数文件操作
    Python中的内置函数
    function(函数)中的动态参数
    copy深浅拷贝
    collections模块
    set集合
    字典dict常用方法
  • 原文地址:https://www.cnblogs.com/xingyunblog/p/8656744.html
Copyright © 2011-2022 走看看