jieba(结巴)分词整和Elasticsearch

Jieba 分词 安装到 Elasticsearch 并结合 Java 实现是一个复杂但有效的方案。由于 Elasticsearch 并没有原生支持结巴分词,需要通过自定义插件或者应用层预处理的方式来实现。

下面是两种方案来整合 Jieba 分词与 Elasticsearch 并结合 Java 使用的具体步骤。

方案一:自定义 Elasticsearch 分词插件(复杂度较高)

在这个方案中,你需要开发一个自定义的 Elasticsearch 分词插件,将 Jieba 分词集成进 Elasticsearch。这个方法需要对 Elasticsearch 插件开发有一定了解。

1. 创建自定义 Elasticsearch 插件
  1. 配置 Maven 项目

    使用 Maven 创建一个项目,配置 pom.xml,让它依赖于 Elasticsearch 的插件开发库。

    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.plugin</groupId>
            <artifactId>elasticsearch-plugin-classloader</artifactId>
            <version>7.17.7</version> <!-- 对应你的ES版本 -->
        </dependency>
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
            <version>7.17.7</version> <!-- 对应你的ES版本 -->
        </dependency>
         <dependency>
            <groupId>com.huaban</groupId>
            <artifactId>jieba-analysis</artifactId>
            <version>1.0.2</version><!-- 对应你选择的结巴依赖 -->
         </dependency>
    </dependencies>
    

  2. 编写分词插件

    创建一个继承 TokenizerFactory 的类,利用 JiebaAnalyzer 来进行分词。

    import com.huaban.analysis.jieba.JiebaSegmenter;
    import org.apache.lucene.analysis.Tokenizer;
    import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
    import org.apache.lucene.util.AttributeFactory;
    
    public class JiebaTokenizer extends Tokenizer {
        private final CharTermAttribute charTermAttr = addAttribute(CharTermAttribute.class);
        private JiebaSegmenter segmenter = new JiebaSegmenter();
        private Iterator<String> iterator;
    
        @Override
        public boolean incrementToken() throws IOException {
            clearAttributes();
            if (iterator == null) {
                String content = new String(input.readAllChars());
                iterator = segmenter.process(content, JiebaSegmenter.SegMode.SEARCH).stream().map(item -> item.word).iterator();
            }
            if (iterator.hasNext()) {
                charTermAttr.append(iterator.next());
                return true;
            }
            return false;
        }
    }
    

  3. 实现分词器工厂类

    实现工厂类用于创建 Jieba 分词器:

    import org.elasticsearch.index.analysis.AbstractTokenizerFactory;
    import org.elasticsearch.index.analysis.TokenizerFactory;
    import org.elasticsearch.index.settings.IndexSettings;
    
    public class JiebaTokenizerFactory extends AbstractTokenizerFactory {
        public JiebaTokenizerFactory(IndexSettings indexSettings) {
            super(indexSettings);
        }
    
        @Override
        public Tokenizer create() {
            return new JiebaTokenizer();
        }
    }
    
  4. 配置插件描述文件

    plugin-descriptor.properties 中配置插件信息:

    plugin.name=jieba-analysis
    plugin.description=Jieba Analysis Plugin for Elasticsearch
    plugin.classname=com.example.JiebaAnalysisPlugin
    

  5. 打包插件并安装到 Elasticsearch

         使用 Maven 打包插件,并将其安装到 Elasticsearch:

./bin/elasticsearch-plugin install file:///path/to/jieba-analysis-plugin.zip

然后重启 Elasticsearch。

2. 使用 Java 与 Elasticsearch 交互
  1. 创建 Elasticsearch 客户端

    使用 Elasticsearch 提供的 Java 高级客户端进行与 ES 的交互:

    import org.elasticsearch.client.RestHighLevelClient;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RequestOptions;
    import org.elasticsearch.action.index.IndexRequest;
    import org.elasticsearch.common.xcontent.XContentType;
    
    public class ElasticSearchClient {
        private static final RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(new HttpHost("localhost", 9200, "http")));
    
        public static void main(String[] args) throws IOException {
            IndexRequest request = new IndexRequest("test_index")
                .source("{ \"content\": \"我喜欢Elasticsearch\" }", XContentType.JSON);
            client.index(request, RequestOptions.DEFAULT);
            client.close();
        }
    }
    

  2. 创建索引并使用 Jieba 分词器

    在创建索引时,指定你自定义的 jieba_tokenizer 分词器:

    PUT /test_index
    {
      "settings": {
        "analysis": {
          "tokenizer": {
            "jieba_tokenizer": {
              "type": "jieba_tokenizer"
            }
          },
          "analyzer": {
            "jieba_analyzer": {
              "type": "custom",
              "tokenizer": "jieba_tokenizer"
            }
          }
        }
      }
    }
    

3. 查询测试

使用自定义的 jieba_analyzer 对文档进行查询:

GET /test_index/_search
{
  "query": {
    "match": {
      "content": {
        "query": "Elasticsearch",
        "analyzer": "jieba_analyzer"
      }
    }
  }
}

方案二:应用层预处理分词(更简单,推荐)

与其直接在 Elasticsearch 中集成 Jieba 分词器,另一种更简单且灵活的方法是在应用层使用结巴分词,然后将处理后的分词结果存入 Elasticsearch。这种方案的实现步骤相对较为简单。

1. 在应用层进行结巴分词
  1. 使用 Jieba 分词

    在 Java 项目中使用结巴分词的 Java 版本 jieba-analysis

            <dependency>
                <groupId>com.huaban</groupId>
                <artifactId>jieba-analysis</artifactId>
                <version>1.0.2</version>
            </dependency>

  2. 分词示例

    使用 Jieba 分词对输入的中文文本进行处理:

    import com.huaban.analysis.jieba.JiebaSegmenter;
    
    public class JiebaExample {
        public static void main(String[] args) {
            JiebaSegmenter segmenter = new JiebaSegmenter();
            String text = "我喜欢学习Elasticsearch";
            System.out.println(segmenter.process(text, JiebaSegmenter.SegMode.SEARCH));
        }
    }
    

    输出结果类似于:[[我, 0, 1], [喜欢, 1, 3], [学习, 3, 5], [elasticsearch, 5, 18]]

  3. 将分词结果存入 Elasticsearch

    Jieba 分词后的详细结构信息。这个结果包含了每个分词的起始位置和结束位置,而不仅仅是分词的文本。

    JiebaSegmenter 的 process 方法返回的是 List<SegToken>,而 SegToken 是一个对象,里面包括了:

    1.word(词语本身),比如 "我"、"喜欢"、"学习"。
    2.start offset(词的起始位置),表示词语在原始文本中的开始字符索引。
    3.end offset(词的结束位置),表示词语在原始文本中的结束字符索引。
    因此,返回的结构类似于 [词语, 起始位置, 结束位置]。

    如果你只想获取分词结果,而不需要起始位置和结束位置的信息,你可以将 SegToken 转换为词语本身,并将处理后的分词结果作为数组或者字符串存入 Elasticsearch:

    import com.huaban.analysis.jieba.JiebaSegmenter;
    import org.elasticsearch.xcontent.XContentBuilder;
    import org.elasticsearch.xcontent.XContentFactory;
    
    public class JiebaExample {
        public static void main(String[] args) {
           JiebaSegmenter segmenter = new JiebaSegmenter();
                String text = "我喜欢学习Elasticsearch";
                // 获取分词结果
                List<String> tokens = segmenter.process(text, JiebaSegmenter.SegMode.SEARCH).stream().map(item -> item.word).collect(Collectors.toList());
    
                // 构建 JSON 文档
                XContentBuilder builder = XContentFactory.jsonBuilder();
                builder.startObject();
                builder.field("content", text);
                builder.field("tokens", tokens);  // 自动转换为 JSON 数组
                builder.endObject();
    
                // 创建 IndexRequest
                IndexRequest request = new IndexRequest("test_index")
                        .source(builder);
    
                // 执行请求
                client.index(request, RequestOptions.DEFAULT);
        }

2. 在 Elasticsearch 中查询

当用户查询时,你可以直接对分词后的字段进行匹配查询:

GET /test_index/_search
{
  "query": {
    "match": {
      "tokens": "Elasticsearch"
    }
  }
}

总结

  • 方案一:自定义 Elasticsearch 分词插件:这种方式更为复杂,但能将 Jieba 分词完全集成到 Elasticsearch 中,提供实时分词处理。需要编写插件、打包、安装等步骤。
  • 方案二:应用层分词处理:这种方式更为简单,灵活性高,适合在将数据存入 Elasticsearch 之前先在应用层进行分词处理,不需要对 Elasticsearch 进行定制。

对于大部分应用场景,方案二 更为推荐,因为它简化了开发流程,并且允许你在应用层使用更加灵活的分词策略。如果对自定义插件有深入需求,方案一 则可以作为高级选项。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值