05_Lucene中文分词器

2018-01-07  本文已影响0人  对方不想理你并向你抛出一个异常

分析器(Analyzer)的执行过程

如下图是语汇单元的生成过程:


lucene分词器执行流程.png

从一个Reader字符流开始,创建一个基于Reader的Tokenizer分词器,经过三个TokenFilter生成语汇单元Token。
要看分析器的分析效果,只需要看Tokenstream中的内容就可以了。每个分析器都有一个方法tokenStream,返回一个tokenStream对象。

Lucene自带中文分析器

上边两个分词器无法满足需求。

第三方中文分词器

使用IK

使用方法:

config为src目录

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">  
<properties>  
    <comment>IK Analyzer 扩展配置</comment>
    <!--用户可以在这里配置自己的扩展字典 -->
    <entry key="ext_dict">ext.dic;</entry> 

    <!--用户可以在这里配置自己的扩展停止词字典-->
    <entry key="ext_stopwords">stopword.dic;</entry> 
    
</properties>

注意:mydict.dic和ext_stopword.dic文件的格式为UTF-8,注意是无BOM 的UTF-8 编码。

package cn.huahcao.lucene;

import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class IndexManagerTest {
    @Test
    public void testCreateIndex() throws Exception{
        //采集文件系统中的文档数据,放入lucene中
        //文档列表,保存Document
        List<Document> docList = new ArrayList<Document>();

        //指定文件所在的目录
        File dir = new File("G:\\Java\\JavaEE\\09_SSM\\lucene_day01\\参考资料\\searchsource");

        //循环取出文件
        for (File file:dir.listFiles()){
            //文件名称
            String fileName = file.getName();
            //文件内容
            String fileContext = FileUtils.readFileToString(file);
            //文件大小
            Long fileSize = FileUtils.sizeOf(file);
            //文档对象。文件系统中的一个文件就是一个Document对象
            Document doc = new Document();
            /**
             * 第一个参数:域名
             * 第二个参数:域值
             * 第三个参数:是否存储,是为Yes,不存储为No
             */
//            TextField nameFiled = new TextField("fileName",fileName, Field.Store.YES);
//            TextField contextFiled = new TextField("fileContent",fileContent, Field.Store.YES);
//            TextField sizeFiled = new TextField("fileSize",fileSize.toString(), Field.Store.YES);

            //是否分词:要,因为它要索引,并且它不是一个整体,分词有意义
            //是否索引:要,因为要通过它来进行搜索
            //是否存储:要,因为要直接在页面上显示
            TextField nameFiled = new TextField("fileName", fileName, Field.Store.YES);

            //是否分词: 要,因为要根据内容进行搜索,并且它分词有意义
            //是否索引: 要,因为要根据它进行搜索
            //是否存储: 可以要也可以不要,不存储搜索完内容就提取不出来
            TextField contextFiled = new TextField("fileContext", fileContext, Field.Store.NO);

            //是否分词: 要, 因为数字要对比,搜索文档的时候可以搜大小, lunene内部对数字进行了分词算法
            //是否索引: 要, 因为要根据大小进行搜索
            //是否存储: 要, 因为要显示文档大小
            LongField sizeFiled = new LongField("fileSize", fileSize, Field.Store.YES);

            //将所有的域存入文档中
            doc.add(nameFiled);
            doc.add(contextFiled);
            doc.add(sizeFiled);

            //将文档存入文档集合中
            docList.add(doc);
        }

        //创建分词器,StandardAnalyzer标准分词器,标准分词器对英文分词效果很好,对中文是单字分词
        Analyzer analyzer = new IKAnalyzer();
        //指定索引和文档存储的目录
        FSDirectory directory = FSDirectory.open(new File("G:\\Java\\JavaEE\\09_SSM\\lucene_day01\\tmp"));
        //创建写对象的初始化对象
        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3,analyzer);
        //创建索引和文档写对象
        IndexWriter indexWriter = new IndexWriter(directory , config);

        //将文档加入到索引和文档的写对象中
        for (Document doc:docList){
            indexWriter.addDocument(doc);
        }
        //提交
        indexWriter.commit();
        //关闭流
        indexWriter.close();
    }
}

从上面可以看出中文是按词义分的,而不是之前的一个字一个字的分

上一篇下一篇

猜你喜欢

热点阅读