简介

分词器:采集到的数据会存储到Document对象的Field域中,分词器就是将Document中Field的value 值切分成一个一个的词。
停用词:停用词是为节省存储空间和提高搜索效率,搜索程序在索引页面或处理搜索请求时会自动忽略某 些字或词,这些字或词即被称为Stop Words(停用词)。比如语气助词、副词、介词、连接词等,通常自 身并无明确的意义,只有将其放入一个完整的句子中才有一定作用,如常见的“的”、“在”、“是”、“啊” 、 a、an、the 等。

扩展词: 扩展词 就是分词器默认不会切出的词 但我们希望分词器切出这样的词 。 过滤:包括去除标点符号过滤、去除停用词过滤(的、是、a、an、the等)、大写转小写、词的形还原 (复数形式转成单数形参、过去式转成现在式。。。)等。

默认使用的是标准分析器StandardAnalyzer

查询分析器效果
使用Analyzer对象的tokenStream方法返回一个TokenStream对象.词对象中包含了最终分词结果.

实现步骤

  1. 创建一个Analyzer对象,StandardAnalyzer对象
  2. 使用分析器对象的tokenStream方法获得一个TokenStream对象
  3. 向TokenStream对象中设置一个引用,相当于一个指针
  4. 调用while循环遍历TokenStream对象
  5. 关闭TokenStream对象

    分析器

    1. @Test
    2. public void testTokenStream() throws IOException {
    3. //1. 创建一个Analyzer对象,StandardAnalyzer对象
    4. StandardAnalyzer analyzer = new StandardAnalyzer();
    5. //Analyzer analyzer = new IKAnalyzer();
    6. //2. 使用分析器对象的tokenStream方法获得一个TokenStream对象, 域名称,分析的文本内容
    7. TokenStream tokenStream = analyzer.tokenStream("", "数据库like查询和全文检索的区别");
    8. //3. 向TokenStream对象中设置一个引用,相当于一个指针
    9. CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
    10. //4. 调用TokenStream对象的rest方法.如果不调用抛异常
    11. tokenStream.reset();
    12. //5. 调用while循环遍历TokenStream对象
    13. while (tokenStream.incrementToken()) {
    14. System.out.println(charTermAttribute.toString());
    15. }
    16. //6. 关闭TokenStream对象
    17. tokenStream.close();
    18. /**
    19. * 输出
    20. * 数
    21. * 据
    22. * 库
    23. * like
    24. * 查
    25. * 询
    26. * 和
    27. * 全
    28. * 文
    29. * 检
    30. * 索
    31. * 的
    32. * 区
    33. * 别
    34. */
    35. }

扩展ik中文分词

IKAnalyze的使用方法

  1. 把IKAnalyzer的jar包添加到工程中
  2. 把配置文件和扩展词典添加到工程的classpath下

注意:hotword.dic和ext_stopword.dic文件的格式为UTF-8,注意是无BOM 的UTF-8编码。也就是说禁止使用windows记事本编辑扩展词典文件

扩展词典: 添加一些新词
停用词词典: 无意义的词或者敏感词汇

使用方法:
第一步:把jar包添加到工程中
第二步:把配置文件和扩展词典和停用词词典添加到classpath下

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

xml可以配置

<?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">hotword.dic;</entry>

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

</properties>
@Test
public void testTokenStream() throws IOException {
    //1. 创建一个分词对象
    IKAnalyzer analyzer = new IKAnalyzer();

    //2. 使用分析器对象的tokenStream方法获得一个TokenStream对象, 域名称,分析的文本内容
    TokenStream tokenStream = analyzer.tokenStream("", "1.2.1全文检索");

    //3. 向TokenStream对象中设置一个引用,相当于一个指针
    CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);

    //4. 调用TokenStream对象的rest方法.如果不调用抛异常
    tokenStream.reset();

    //5. 调用while循环遍历TokenStream对象
    while (tokenStream.incrementToken()) {
        System.out.println(charTermAttribute.toString());
    }

    //6. 关闭TokenStream对象
    tokenStream.close();
}

扩展字段

停用词典

1.2

输出

加载扩展词典:hotword.dic
加载扩展停止词典:stopword.dic
1.2.1
全文
文
检索

创建索引使用ik分词

IndexWriterConfig那指定ik

@Test
    public void testCreateIndex() throws Exception {
        // 1. 采集数据  和 之前完全相同
        List<Book> bookList = new ArrayList<Book>();
        Book booka = new Book();
        booka.setId(1);
        booka.setDesc("数据库like查询和全文检索的区别");
        booka.setName("lucene");
        booka.setPrice(100.45f);
        bookList.add(booka);
        // 2. 创建Document文档对象
        List<Document> documents = new ArrayList<>();
        for (Book book : bookList) {
            Document document = new Document();
            // IntPoint  分词 索引 不存储 存储结合  StoredField
            Field id = new IntPoint("id", book.getId());
            Field id_v = new StoredField("id", book.getId());
            // 分词、索引、存储 TextField
            Field name = new TextField("name", book.getName(), Field.Store.YES);
            // 分词、索引、不存储 但是是数字类型,所以使用FloatPoint
            Field price = new FloatPoint("price", book.getPrice());
            // 分词、索引、存储 TextField 为了看到分词效果设置成存储
            Field desc = new TextField("desc", book.getDesc(), Field.Store.YES);

            // 将field域设置到Document对象中
            document.add(id);
            document.add(id_v);
            document.add(name);
            document.add(price);
            document.add(desc);

            documents.add(document);
        }

        //3.创建StandardAnalyzer 分词器 对文档进行分词  把 StandardAnalyzer 变成 IKAnalyer
        //Analyzer analyzer  = new StandardAnalyzer();
        Analyzer analyzer = new IKAnalyzer();
        // 创建Directory   和 IndexWriterConfig 对象
        Directory directory = FSDirectory.open(Paths.get("/Users/xiajiandong/Desktop/luceneTest/index5"));
        IndexWriterConfig indexWriterConfig = new IndexWriterConfig(analyzer);
        // 4.创建IndexWriter 写入对象
        IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
        // 添加文档对象
        for (Document doc : documents) {
            indexWriter.addDocument(doc);
        }
        // 释放资源
        indexWriter.close();
    }

源码

@Override
  protected TokenStreamComponents createComponents(final String fieldName) {
      final StandardTokenizer src = new StandardTokenizer();
      src.setMaxTokenLength(maxTokenLength);
      TokenStream tok = new LowerCaseFilter(src);
      tok = new StopFilter(tok, stopwords);
      return new TokenStreamComponents(src, tok) {
          @Override
          protected void setReader(final Reader reader) {
              // So that if maxTokenLength was changed, the change takes
              // effect next time tokenStream is called:
              src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
              super.setReader(reader);
          }
      };
  }

Tokenizer就是分词器,负责将reader转换为语汇单元即进行分词处理,Lucene提供了很多的分词器, 也可以使用第三方的分词,比如IKAnalyzer一个中文分词器。

TokenFilter是分词过滤器,负责对语汇单元进行过滤,TokenFilter可以是一个过滤器链儿,Lucene提 供了很多的分词器过滤器,比如大小写转换、去除停用词等。

如下图是语汇单元的生成过程:
创建一个Tokenizer分词器,经过三个TokenFilter生成语汇单元Token。
Tokenizer —->TokenFilter(标准过滤)—->TokenFilter(大小写过滤)—->TokenFilter(停用词过滤)—->Tokens
比如下边的文档经过分析器分析如下:
原文档内容:
Lucene is java full text search lib
分析后得到的多个语汇单元:
lucene java full text search lib

注意:搜索使用的分词器要和索引使用的分词器一致。