文档章节

solr词库实时更新维护

penngo
 penngo
发布于 2016/04/19 16:43
字数 896
阅读 188
收藏 6
点赞 2
评论 0

1、solr导入到eclipse

下载solr-5.4.1-src.tgz,官网地址http://www.apache.org/dyn/closer.lua/lucene/solr/5.4.1

解压solr-5.4.1-src.tgz到D:\project\java\solr-5.4.1目录,在目录的命令行下输入ant eclipse,然后进入漫长的等待过程,中间需要从网上下载很多依赖包。

编译时,可能会报Ivy could not be found in you ant classpath,去ivy官网(http://ant.apache.org/ivy/download.cgi)下载ivy.jar即可。

直到出现BUILD SUCCESSFUL,使用eclipse导入。

打开org.apache.solr.client.solrj.StartSolrJetty,设置solr.solr.home

public class StartSolrJetty 
{
  public static void main( String[] args ) 
  {
    System.setProperty("solr.solr.home", "solr/example/solr");

    Server server = new Server();
    ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory());
    // Set some timeout options to make debugging easier.
    connector.setIdleTimeout(1000 * 60 * 60);
    connector.setSoLingerTime(-1);
    connector.setPort(8983);
    server.setConnectors(new Connector[] { connector });
    
    WebAppContext bb = new WebAppContext();
    bb.setServer(server);
    bb.setContextPath("/solr");
    bb.setWar("solr/webapp/web");

    server.setHandler(bb);

    try {
      System.out.println(">>> STARTING EMBEDDED JETTY SERVER, PRESS ANY KEY TO STOP");
      server.start();
      while (System.in.available() == 0) {
        Thread.sleep(5000);
      }
      server.stop();
      server.join();
    }
    catch (Exception e) {
      e.printStackTrace();
      System.exit(100);
    }
  }
}

2、实时更新词库

本文使用Jcseg这个中文分词库,查看org.lionsoul.jcseg.analyzer.v5x.JcsegTokenizerFactory的源码,词库数据保存在ADictionary dic这个变量中,

public class JcsegTokenizerFactory extends TokenizerFactory 
{
    private int mode;
    private JcsegTaskConfig config = null;
    private ADictionary dic = null;  // 词库变量

    /**
     * set the mode arguments in the schema.xml 
     *     configuration file to change the segment mode for jcseg
     *
     */
    public JcsegTokenizerFactory(Map<String, String> args)
    {
        super(args);
        String _mode = args.get("mode");
        if ( _mode == null ) mode = JcsegTaskConfig.COMPLEX_MODE;
        else 
        {
            _mode = _mode.toLowerCase();
            
            if ( "simple".equals(_mode) )
                mode = JcsegTaskConfig.SIMPLE_MODE;
            else if ( "detect".equals(_mode) )
                mode = JcsegTaskConfig.DETECT_MODE;
            else
                mode = JcsegTaskConfig.COMPLEX_MODE;
        }
        
        //initialize the task config and the dictionary
        config = new JcsegTaskConfig();
        dic = DictionaryFactory.createDefaultDictionary(config);
    }
    
    public void setConfig( JcsegTaskConfig config ) 
    {
        this.config = config;
    }
    
    public void setDict( ADictionary dic ) 
    {
        this.dic = dic;
    }
    
    public JcsegTaskConfig getTaskConfig() 
    {
        return config;
    }
    
    public ADictionary getDict()
    {
        return dic;
    }

    @Override
    public Tokenizer create( AttributeFactory factory ) 
    {
        try {
            return new JcsegTokenizer(mode, config, dic);
        } catch (JcsegException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return null;
    }
}

继续查看org.apache.solr.handler.FieldAnalysisRequestHandler代码,知道可以通过SolrQueryRequest获取到TokenizerFactory

只需要取得JcsegTokenizerFactory对应实例,就能取得dic,通过add和remove方法实时更新词库。

dic.add(ILexicon.CJK_WORD, word, IWord.T_CJK_WORD);

dic.remove(ILexicon.CJK_WORD, word);


自定义实现request handler,在request handler里面通过SolrQueryRequest取得IndexSchema->IndexAnalyzer->TokenizerFactory,最终取得dic实例操作词库,内存中的词库更新后,也需要保存到本地词库文件中,避免重启后丢失词库。实现代码

package com.penngo.solr;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.util.TokenizerFactory;
import org.apache.solr.analysis.TokenizerChain;
import org.apache.solr.common.StringUtils;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.handler.RequestHandlerBase;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.FieldType;
import org.apache.solr.schema.IndexSchema;
import org.lionsoul.jcseg.analyzer.v5x.JcsegTokenizerFactory;
import org.lionsoul.jcseg.tokenizer.core.ADictionary;
import org.lionsoul.jcseg.tokenizer.core.ILexicon;
import org.lionsoul.jcseg.tokenizer.core.IWord;
import org.lionsoul.jcseg.tokenizer.core.JcsegTaskConfig;

import com.fasterxml.jackson.databind.ObjectMapper;

public class TestHandler extends RequestHandlerBase{
  public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
    SolrParams params = req.getParams();
    System.out.println("params=======" + params);
    JcsegTaskConfig config = new JcsegTaskConfig();
    String addDatas = params.get("add");
    Map<String,Object> dataResult = new HashMap<String,Object>();
    ObjectMapper mapper = new ObjectMapper();
    String lexiconPath = config.getLexiconPath()[0];
    String fileLex = lexiconPath + "/lex-penngo.lex";
    IndexSchema indexSchema = req.getSchema();
    FieldType filetype = indexSchema.getFieldTypeByName("textComplex");
    Analyzer analyzer = filetype.getIndexAnalyzer();
    TokenizerChain tokenizerChain = (TokenizerChain) analyzer;
    TokenizerFactory tfac = tokenizerChain.getTokenizerFactory();
    
    if (tfac instanceof JcsegTokenizerFactory) {
      JcsegTokenizerFactory jtf = (JcsegTokenizerFactory) tfac;
      ADictionary dic = jtf.getDict();
      if (dic != null) {
        if (StringUtils.isEmpty(addDatas) == false) {
          FileOutputStream fos = new FileOutputStream(new File(fileLex), true);
          OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8");
          BufferedWriter bw = new BufferedWriter(osw);
          ArrayList<List<String>> wordList = mapper.readValue(addDatas, ArrayList.class);
          for(List<String> word: wordList){
              String name = word.get(0);
              String type = word.get(1);
              String pinyin = word.get(2);
              String syn = word.get(3);
              
              IWord iword = dic.get(ILexicon.CJK_WORD, name);
              // 如果不存在,则添加到词库
              if (iword == null) {
                dic.add(ILexicon.CJK_WORD, name, IWord.T_CJK_WORD);
                iword = dic.get(ILexicon.CJK_WORD, name);
                iword.addPartSpeech(type);
                iword.setPinyin(pinyin);
                String[] syns = syn.split(",");
                for (String s : syns) {
                  iword.addSyn(s);
                }
                StringBuffer sff = new StringBuffer();
                sff.append(name).append("/").append(type).append("/").append(pinyin).append("/").append(syn);
                // 把分词添加到词库文件lex-penngo.lex中
                bw.write(sff.toString());
                bw.newLine();
              }
          }
          bw.close();
          osw.close();
          fos.close();
        }
        
        dataResult.put("status", "ok");
      }
    }
    rsp.add("response", dataResult);
  }
  
  public String getDescription() {
    return null;
  }
}

solrconfig.xml添加配置

<requestHandler name="/test" class="com.penngo.solr.TestHandler">
 <lst name="defaults">
   <str name="wt">json</str>
   <str name="indent">true</str>
 </lst>
</requestHandler>

以"公众号"这个词来测试

jcseg自带词库分词结果



客户端通过接口添加分词后结果,php代码

<?php
$url = "http://localhost:8983/solr/news/test";
$data = array(
    array("公众号", "n", "gong zhong hao", "大众号,社会号,penngo")
);

$url = $url . "?add=" . urlencode(json_encode($data));
echo $url . "\n";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$result = curl_exec($ch);
curl_close($ch);
print_r($result);
?>

© 著作权归作者所有

共有 人打赏支持
penngo
粉丝 76
博文 98
码字总数 55112
作品 2
广州
程序员
Jcseg 2.1.0 发布 - Java 开源中文分词器

Jcseg是基于mmseg算法的一个轻量级中文分词器,同时集成了关键字提取,关键短语提取,关键句子提取和文章自动摘要等功能,并且提供了一个基于Jetty的web服务器,方便各大语言直接http调用,同...

狮子的魂
2017/01/09
2.7K
10
Jcseg 1.9.8 发布,新增检索模式/细粒度切分

Jcseg是基于mmseg算法的一个轻量级开源中文分词器,同时集成了关键字提取,关键短语提取,关键句子提取和文章自动摘要等功能,并且提供了最新版本的lucene, solr, elasticsearch的分词接口。...

狮子的魂
2016/06/13
3.8K
25
Jcseg 1.9.9 发布,Maven 仓库上传+无痛安装与测试

Jcseg是基于mmseg算法的一个轻量级中文分词器,同时集成了关键字提取,关键短语提取,关键句子提取和文章自动摘要等功能,并且提供了一个基于Jetty的web服务器,方便各大语言直接http调用,同...

狮子的魂
2016/07/07
3.3K
39
Solr Apache Solr 初级教程(介绍、安装部署、Java接口、中文分词)

Apache Solr 介绍 Solr 是什么? Solr 是一个开源的企业级搜索服务器,底层使用易于扩展和修改的Java 来实现。服务器通信使用标准的HTTP 和XML,所以如果使用Solr 了解Java 技术会有用却不是...

David_Tio
2013/12/05
0
0
jcseg-1.8.8发布 - 词库更新自动加载+自定义配置文件+中英混合词识别

jcseg是使用java开发的一款开源中文分词器, 并且提供了最新版本的lucene和solr分词接口. jcseg-1.8.8版本发布了, 这次的更新项比较多, 主要如下: 1. 中英混合词的识别: 不是已经支持中英混合...

狮子的魂
2013/07/10
1K
11
狮子的魂/jcseg

Jcseg是什么? Jcseg是基于mmseg算法的一个轻量级中文分词器,同时集成了关键字提取,关键短语提取,关键句子提取和文章自动摘要等功能,并且提供了一个基于Jetty的web服务器,方便各大语言直...

狮子的魂
2013/11/16
0
0
Jcseg-1.9.6 发布,词性补全+lucene/solr/elasticsearch 最新版本支持

Jcseg[dʒɛ'ke'sɛ]是使用Java开发的一个轻量级中文分词器,使用流行的mmseg算法实现,并且提供了最高版本的lucene-5.1.0(发布时我发现5.2.0又发布了 ),solr-5.1.0,elasticsearch-1.5.2...

狮子的魂
2015/06/09
2.7K
9
jcseg-1.8.9 发布-词性标注+标点切分+IntArrayList优化+bug修复

jcseg是使用java开发的一款开源中文分词器, 并且提供了最新版本的lucene和solr分词接口. jcseg-1.8.9发布了: 具体更新如下: 1. 保留英文半全角标点和CJK标点符号切分(可通过停止词过滤掉,默认...

狮子的魂
2013/09/09
1K
13
solr索引时分词,如果更新词库了怎么办??

最近在用solr做一个项目,不断开发不断完善,但同事提出一个问题,以前没考虑过,想了想好像确实有问题。 问题描述: 目前索引的时候分词器采用的是max-word(当然与算法无关),目前我的词库...

tianpeng91
2014/06/23
2.3K
4
Java 开源中文分词器--Jcseg

Jcseg 是什么? Jcseg 是基于 mmseg 算法的一个轻量级开源中文分词器,同时集成了关键字提取,关键短语提取,关键句子提取和文章自动摘要等功能,并且提供了最新版本的 lucene, solr, elasti...

狮子的魂
2012/10/19
35.8K
29

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式 Factory工厂模式 Singleton单例模式 Delegate委派模式 Strategy策略模式 Prototype原型模式 Template模板模式 Spring5 beans 接口实例化 代理Bean操作 ...

小致dad
16分钟前
0
0
SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
9
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
12
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
203
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部