欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Lucene-2.0学习文档(1) 博客分类: 全文检索 lucene搜索引擎全文检索多线程应用服务器 

程序员文章站 2024-03-18 19:24:22
...

 

[原创]Lucene-2.0学习文档

作者:Javafish(likunkun)

Email:javafish@sunxin.org

Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。

其功能非常的强大,api也很简单。总得来说用Lucene来进行建立

和搜索和操作数据库是差不多的(有点像),Document可以看作是

数据库的一行记录,Field可以看作是数据库的字段。用lucene实

现搜索引擎就像用JDBC实现连接数据库一样简单。

<o:p></o:p>

Lucene2.0,它与以前广泛应用和介绍的Lucene <st1:chsdate month="12" islunardate="False" day="30" year="1899" w:st="on" isrocdate="False">1.4.3</st1:chsdate>并不兼容。

<o:p></o:p>

Lucene2.0的下载地址是http://apache.justdn.org/lucene/java/

<o:p></o:p>

大家先看一个例子,通过这个例子来对lucene的一个大概的认识。<o:p></o:p>

一个Junit测试用例:(为了让代码清晰好看,我们将异常都抛出)<o:p></o:p>

a)    这是一个建立文件索引的例子<o:p></o:p>

public void testIndexHello() throws IOException<o:p></o:p>

    {<o:p></o:p>

        Date date1 = new Date(); <o:p></o:p>

        //可以说是创建一个新的写入工具<o:p></o:p>

        //第一个参数是要索引建立在哪个目录里<o:p></o:p>

        //第二个参数是新建一个文本分析器,这里用的是标准的大家也可以自己写一个<o:p></o:p>

        //第三个参数如果是true,在建立索引之前先将c:\\index目录清空。<o:p></o:p>

        IndexWriter writer = new IndexWriter("c:\\index",new StandardAnalyzer(),true);<o:p></o:p>

        <o:p></o:p>

//      这个是数据源的文件夹<o:p></o:p>

        File file = new File("c:\\file");<o:p></o:p>

        /**<o:p></o:p>

         * 例子主要是将C:\\file目录下的文件的内容进行建立索引,将文件路径作为搜索内容的附属.<o:p></o:p>

         */<o:p></o:p>

        <o:p></o:p>

        if(file.isDirectory())<o:p></o:p>

        {<o:p></o:p>

            String[] fileList = file.list();<o:p></o:p>

            for (int i = 0; i < fileList.length; i++)<o:p></o:p>

            {<o:p></o:p>

//              建立一个新的文档,它可以看作是数据库的一行记录<o:p></o:p>

                Document doc = new Document();<o:p></o:p>

                File f = new File(file,<o:p></o:p>

                        fileList[i]);<o:p></o:p>

                Reader reader = new BufferedReader(new FileReader(f));<o:p></o:p>

                doc.add(new Field("file",reader));//doument添加field<o:p></o:p>

                doc.add(new Field("path",f.getAbsolutePath(),Field.Store.YES,Field.Index.NO));<o:p></o:p>

                writer.addDocument(doc);<o:p></o:p>

            }<o:p></o:p>

            <o:p></o:p>

        }<o:p></o:p>

        writer.close();//这一步是必须的,只有这样数据才会被写入索引的目录里<o:p></o:p>

        Date date2 = new Date();<o:p></o:p>

        System.out.println("用时"+(date2.getTime()-date1.getTime())+"毫秒");<o:p></o:p>

}<o:p></o:p>

注意:因为建立索引本来就是费时,所以说最后输出的用时会比较长,请不要奇怪。<o:p></o:p>

b)一个通过索引来全文检索的例子<o:p></o:p>

public void HelloSearch() throws IOException, ParseException<o:p></o:p>

    {<o:p></o:p>

        IndexSearcher indexSearcher = new IndexSearcher("c:\\index");//和上面的IndexWriter一样是一个工具<o:p></o:p>

        QueryParser queryParser = new QueryParser("file",//这是一个分词器<o:p></o:p>

                new StandardAnalyzer());<o:p></o:p>

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));<o:p></o:p>

        Query query = queryParser.parse(br.readLine());//这个地方Query是抽象类大家也注意一下,下面会讲到的<o:p></o:p>

        Hits hits = indexSearcher.search(query);<o:p></o:p>

        Document doc = null;<o:p></o:p>

        System.out.print("正搜索................");<o:p></o:p>

        for (int i = 0; i < hits.length(); i++)<o:p></o:p>

        {<o:p></o:p>

            doc = hits.doc(i);<o:p></o:p>

            System.out.println("内容是:"+doc.get("file"));//注意这里输出的是什么<o:p></o:p>

            System.out.println("文件的路径是:" + doc.get("path"));<o:p></o:p>

        }<o:p></o:p>

    }<o:p></o:p>

通过上面的两个例子应该可以看出Lucene还是比较简单的。<o:p></o:p>

运行一下上面的两个例子,大家可能会说怎么doc.get(file);返回的是空呢,我们马上会讲到。<o:p></o:p>

下面讲一下索引的建立<o:p></o:p>

其实从上面的例子就可以看出建立索引就用到Document,IndexWriter,Field<o:p></o:p>

最简单的步骤就是:<o:p></o:p>

首先分别new 一个DocumentIndexWriter,Field<o:p></o:p>

然后用Doument.add()方法加入Field,<o:p></o:p>

其次用IndexWrtier.addDocument()方法加入Document。<o:p></o:p>

最后调用一下IndexWriter.close()方法关闭输入索引,这一步非常的重要只有调用这个方法索引才会被写入索引的目录里,而这是被很多初学的人所忽略的。<o:p></o:p>

Document没有什么好介绍的,把它的作用看成数据库中的一行记录就行。<o:p></o:p>

Field是一个比较重要的也是比较复杂的:<o:p></o:p>

看一下它的构造函数有5个:<o:p></o:p>

Field(String name, byte[] value, Field.Store store)<o:p></o:p>

Field(String name, Reader reader)<o:p></o:p>

Field(String name, Reader reader, Field.TermVector termVector)<o:p></o:p>

Field(String name, String value, Field.Store store, Field.Index index)<o:p></o:p>

Field(String name, String value, Field.Store store, Field.Index index, Field.TermVector termVector)<o:p></o:p>

Field中有三个内部类:Field.Index,Field.Store,Field.termVector,而构造函数也用到了它们。<o:p></o:p>

注意:termVectorLucene 1.4新增的它提供一种向量机制来进行模糊查询的这个不常用,默认是false不过是什么对于一般查询无影响。<o:p></o:p>

它们的不同的组合,在全文检索中有着不同的作用。看看下面的表吧:<o:p></o:p>

Field.Index<o:p></o:p>

Field.Store<o:p></o:p>

说明<o:p></o:p>

TOKENIZED(分词)<o:p></o:p>

YES<o:p></o:p>

文章的标题或内容(如果是内容的话不能太长)是可以被搜索的<o:p></o:p>

TOKENIZED<o:p></o:p>

NO<o:p></o:p>

文章的标题或内容(内容可以很长)也是可以被看过的<o:p></o:p>

NO<o:p></o:p>

YES<o:p></o:p>

这是不能被搜索的,它只是被搜索内容的附属物。如URL<o:p></o:p>

UN_TOKENIZED<o:p></o:p>

YES/NO<o:p></o:p>

不被分词,它作为一个整体被搜索,搜一部分是搜不出来的<o:p></o:p>

NO<o:p></o:p>

NO<o:p></o:p>

没有这种用法<o:p></o:p>

而对于Field(String name, Reader reader)<o:p></o:p>

Field(String name, Reader reader, Field.TermVector termVector)<o:p></o:p>

他们是Field.Index.TOKENIZEDField.Store.NO的。这就是为什么我们在上面的例子中会出现文章的内容为null了。因为它只是被索引了,而并没有被存储下来。如果一定要看到文章的内容的话可以通过文章的路径得到毕竟文章的路径是作为搜索的附属物被搜索出来了。而我们在Web开发的时候一般是将大数据放在数据库中,不会放在文件系统中,更不会放在索引目录里,因为它太大了操作会加大服务器的负担<o:p></o:p>

下面介绍一下IndexWriter:<o:p></o:p>

它就是一个写入索引的写入器,它的任务比较简单:<o:p></o:p>

1.addDocument()将已经准备好写入索引的document们加入<o:p></o:p>

2.调用close()将索引写入索引目录<o:p></o:p>

先看一下它的构造函数:<o:p></o:p>

IndexWriter(Directory d, Analyzer a, boolean create)

(未完)<o:p></o:p>