posts - 78, comments - 34, trackbacks - 0, articles - 1
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

2010-01-04 传智播客—luncene

Posted on 2010-01-04 21:26 長城 阅读(699) 评论(0)  编辑  收藏

         我们这些网民,见得多了检索应用了。Google、百度、论坛内部搜索、网站内部搜索,这些应用使用的就是检索技术。今天我们学习的主要是针对WEB应用的内部文本检索,比如论坛。我们使用的框架是lucene。授课老师是汤阳光,年轻有为!

 

         搞技术的,看到什么新技术总是十分好奇。先不说googlebaidu吧(他们的专业检索技术很强哦),见到论坛内部的检索功能,就让我十分好奇。我原本以为论坛内部的检索就是模糊查找数据库,但今日的课程让我学习到了论坛内部真正的检索技术。

 

一、信息检索和全文检索

信息检索就是从信息集合中找出与用户需求相关的信息。被检索的信息除了文本外,还有图像、音频、视频等多媒体信息。我们只关注文本的检索,把用户的查询请求和全文中的每一个词进行比较,不考虑查询请求与文本语义上的匹配,这叫做全文检索。在信息检索工具中,全文检索是最具通用性和实用性的。例如,使用百度从一大堆网页中搜出与“传智播客”相关的网页。

 

我们简单看一下检索技术的流程:

请求

clip_image001

 

上面可见索引数据库是十分重要的,简单的说。全文检索系统,将网络上的数据通过某种格式保存到索引库中。当用户发送查询请求时,实质上就是向索引库查询。全文检索引擎负责处理用户的请求用索引库的更新等。

 

小时候查的汉语字典、英语词典我们是如何查询的?当然不是一页一页的翻了,靠的是字典的目录。Lucene的检索方式正是使用了此技术,lucene的索引库格式:

检索目录

 

数据

索引

关键字

索引

Documents…

1

C、汇编

1

汇编比机器在语言高级…C比汇编高级

2

C++

2

C++C高级..

3

JavaJ2E

3

JAVA应用级,最为优秀的语言

4

WEB

4

WEB是真正的计算机

5

你好

5

Hi,你好啊!

 

 

         上面的表只是简单说明lucene索引库的存储格式。我们通过lucene提供的类可以向索引库添加、修改、查询、删除操作

 

         关键字是通过分词器分析出来的,一般情况下各有语言有各字的分词器。分词器的强大提高了查询数据的接近性。

 

二、lucene操作

         我们编写一个对Article对象向lucene索引库的添加、修改、查询、删除操作:

import java.util.ArrayList;

import java.util.List;

import org.apache.lucene.analysis.Analyzer;

import org.apache.lucene.analysis.standard.StandardAnalyzer;

import org.apache.lucene.index.IndexWriter;

import org.apache.lucene.index.Term;

import org.apache.lucene.index.IndexWriter.MaxFieldLength;

import org.apache.lucene.queryParser.MultiFieldQueryParser;

import org.apache.lucene.queryParser.QueryParser;

import org.apache.lucene.search.IndexSearcher;

import org.apache.lucene.search.Query;

import org.apache.lucene.search.TopDocs;

import cn.itcast.cc.lucene.helloword.Article;

import cn.itcast.cc.lucene.helloword.utils.ArticleDocUtils;

 

public class IndexDao {

    // 索引目录

    private String indexPath = "./index";

    // 分词器

    private Analyzer analyzer = new StandardAnalyzer();

 

    /**

     * 保存记录

     *

     * @param art

     */

    public void save(Article art) {

        // lucene的写出索引类

        IndexWriter indexWriter = null;

        try {

            indexWriter = new IndexWriter(this.indexPath, this.analyzer,

                    MaxFieldLength.LIMITED);

            // 添加到索引库

            indexWriter.addDocument(ArticleDocUtils.Article2Doc(art));

        } catch (Exception e) {

            e.printStackTrace();

        }

        // 释放indexWriter

        if (indexWriter != null) {

            try {

                // 使用后一定要关闭

                indexWriter.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

 

    /**

     * 更新记录

     *

     * @param art

     */

    public void update(Article art) {

        IndexWriter indexWriter = null;

        try {

            indexWriter = new IndexWriter(this.indexPath, this.analyzer,

                    MaxFieldLength.LIMITED);

            Term term = new Term("id", art.getId() + "");

            // 更新

            indexWriter.updateDocument(term, ArticleDocUtils.Article2Doc(art));

        } catch (Exception e) {

            e.printStackTrace();

        }

 

        // 释放indexWriter

        if (indexWriter != null) {

            try {

                indexWriter.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

 

    /**

     * 删除记录

     *

     * @param id

     */

    public void delete(int id) {

        IndexWriter indexWriter = null;

        try {

            indexWriter = new IndexWriter(this.indexPath, this.analyzer,

                    MaxFieldLength.LIMITED);

            Term term = new Term("id", id + "");

            // 删除

            indexWriter.deleteDocuments(term);

        } catch (Exception e1) {

            e1.printStackTrace();

        }

 

        // 释放indexWriter

        if (indexWriter != null) {

            try {

                indexWriter.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

    }

 

    /**

     * 查询记录(具有分页功能)

     *

     * @param queryString

     * @param startIndex

     * @param recordCount

     * @return

     */

    public List search(String queryString, int startIndex, int recordCount) {

        List result = new ArrayList();

        IndexSearcher indexSearcher = null;

        try {

            indexSearcher = new IndexSearcher(this.indexPath);

            String[] fields = new String[] {"title","content"};

            // 分析查询条件

            QueryParser queryParser = new MultiFieldQueryParser(fields,

                    this.analyzer);

            // 生成查询对象

            Query query = queryParser.parse(queryString);

            int findTotalRecord = startIndex + recordCount;

            // 查询

            TopDocs topDocs = indexSearcher.search(query, null, findTotalRecord);

            //获取分页数据

            int endIndex = Math.min(startIndex+recordCount,topDocs.totalHits);

            for(int i=startIndex; i<endIndex;i++){

                result.add(indexSearcher.doc(topDocs.scoreDocs[i].doc));

            }

 

        } catch (Exception e1) {

            e1.printStackTrace();

        }

 

        // 释放indexWriter

        if (indexSearcher != null) {

            try {

                indexSearcher.close();

            } catch (Exception e) {

                e.printStackTrace();

            }

        }

        return result;

    }

}

 

         其中使用到的“ArticleDocUtils”如下:

import org.apache.lucene.document.Document;

import org.apache.lucene.document.Field;

import org.apache.lucene.document.Field.Index;

import org.apache.lucene.document.Field.Store;

import cn.itcast.cc.lucene.helloword.Article;

 

public class ArticleDocUtils {

    public static Document Article2Doc(Article art){

        // lucene索引库中的document对象

        Document doc = new Document();

        // 添加到document中的都是field对象,注册其中的key,检索时会用到。

        // Store是否存储,决定对象是临时性还是持久性的

        // Index在库中建立什么样的索引

        doc.add(new Field("id", art.getId()+"", Store.YES, Index.NOT_ANALYZED));

        doc.add(new Field("title", art.getTitle(), Store.YES, Index.ANALYZED));

        doc.add(new Field("content", art.getContent(), Store.YES, Index.ANALYZED));

        return doc;

    }

   

    public static Article Doc2Article(Document doc){

        Article art = new Article();

       

        art.setId(Integer.parseInt(doc.getField("id").stringValue()));

        art.setTitle(doc.getField("title").stringValue());

        art.setContent(doc.getField("content").stringValue());

        return art;

    }

 

         需要导入的jar包:lucene-analyzers-2.4.0.jarlucene-core-2.4.0.jarlucene-highlighter-2.4.0.jar

 

         上面是对lunce的简单操作,明天会讲解检索的分词器、高亮、排序、过滤

 

         汤老师今天有留练习作业,我去做练习了哦~~ lucene很简单、很方便~~


只有注册用户登录后才能发表评论。


网站导航: