热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用solr实现pinyin分词,针对短词搜索,比如电影搜索

1,增加solr拼音查询原理:pinyin4j-2.5.0.jar下载地址:http:sourceforge.netprojectspinyin4jsolr环境使用3.6.2。2,Tok

1,增加solr拼音查询原理:


pinyin4j-2.5.0.jar 
下载地址:  http://sourceforge.net/projects/pinyin4j/
solr环境使用3.6.2。

2,Token代码:

package com.freewebsys.index.analysis;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
import org.apache.commons.lang.StringUtils;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.ngram.NGramTokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;

public class PinyinTokenizer extends Tokenizer {

private static final int DEFAULT_BUFFER_SIZE = 512;

private boolean dOne= false;
private int finalOffset;
private final CharTermAttribute termAtt = addAttribute(CharTermAttribute.class);
private OffsetAttribute offsetAtt = addAttribute(OffsetAttribute.class);
private HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
// 链接字符串.
private String padding_char = " ";

// 构造函数.
public PinyinTokenizer(Reader reader) {
this(reader, DEFAULT_BUFFER_SIZE);
}

public PinyinTokenizer(Reader input, int bufferSize) {
super(input);
termAtt.resizeBuffer(bufferSize);
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
format.setVCharType(HanyuPinyinVCharType.WITH_V);
}

@Override
public final boolean incrementToken() throws IOException {
if (!done) {
clearAttributes();
dOne= true;
int upto = 0;
char[] buffer = termAtt.buffer();
System.out.println(String.valueOf(buffer));
while (true) {
final int length = input.read(buffer, upto, buffer.length
- upto);
if (length == -1)
break;
upto += length;
if (upto == buffer.length)
buffer = termAtt.resizeBuffer(1 + buffer.length);
}
termAtt.setLength(upto);
String str = termAtt.toString();
termAtt.setEmpty();
StringBuilder stringBuilder = new StringBuilder();
StringBuilder firstLetters = new StringBuilder();
StringBuilder cnLetters = new StringBuilder();
StringBuilder allPinYinLetters = new StringBuilder();

for (int i = 0; i char c = str.charAt(i);
if (c <128) {
stringBuilder.append(c);
} else {
try {
String[] strs = PinyinHelper.toHanyuPinyinStringArray(
c, format);
if (strs != null) {
// get first result by default
String first_value = strs[0];
// TODO more than one pinyin
// 拼接中文字符.
cnLetters.append(c);
cnLetters.append(this.padding_char);
// 全部拼音字符.
allPinYinLetters.append(first_value);
// 拼接拼音字符.
stringBuilder.append(first_value);
stringBuilder.append(this.padding_char);
// 拼接首字母字符.
firstLetters.append(first_value.charAt(0));

}
} catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
badHanyuPinyinOutputFormatCombination.printStackTrace();
}
}
}

// let's join them

termAtt.append(stringBuilder.toString());
termAtt.append(this.padding_char);
termAtt.append(cnLetters.toString());
termAtt.append(this.padding_char);
termAtt.append(firstLetters.toString());
termAtt.append(this.padding_char);
// 将全部拼音分词成一个一个输入数据索引。
termAtt.append(mergeNGramPinYin(allPinYinLetters.toString()));

finalOffset = correctOffset(upto);
offsetAtt.setOffset(correctOffset(0), finalOffset);
return true;
}
return false;
}

@Override
public final void end() {
// set final offset
offsetAtt.setOffset(finalOffset, finalOffset);
}

@Override
public void reset(Reader input) throws IOException {
super.reset(input);
this.dOne= false;
}

public static String mergeNGramPinYin(String allPinYin) {
// 读取字符串
StringReader reader = new StringReader(allPinYin);
// 设置临时变量
String[] pinYinBuffer = null;
if (StringUtils.isNotBlank(allPinYin)) {
// 设置数组长度
pinYinBuffer = new String[allPinYin.length()];
StringBuffer tmpAppendPinYin = new StringBuffer();
NGramTokenizer nGramTokenizer = new NGramTokenizer(reader);
for (int i = 0; i try {
// 循环递增
nGramTokenizer.incrementToken();
// 取得解析后的字符串
CharTermAttribute charTermAttribute = nGramTokenizer
.getAttribute(CharTermAttribute.class);
tmpAppendPinYin.append(String.valueOf(
charTermAttribute.buffer()).trim());
// 每次都给数据赋值.
pinYinBuffer[i] = tmpAppendPinYin.toString();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 将结果按照空格合并.
return StringUtils.join(pinYinBuffer, " ");

}

}

PinyinTokenizerFactory:
package com.freewebsys.index.analysis;

import org.apache.lucene.analysis.Tokenizer;
import org.apache.solr.analysis.BaseTokenizerFactory;
import java.io.Reader;

/**
*/
public class PinyinTokenizerFactory extends BaseTokenizerFactory {

@Override
public Tokenizer create(Reader input) {
return new PinyinTokenizer(input);
}

}


3,solr 的schema.xml配置:

对于 index和query分开配置:

positiOnIncrementGap="100">



generateWordParts="1" generateNumberParts="1" catenateWords="0"
catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" />





4,使用分词效果:





如果在管理后台测试可以看到上面的分词结果,就说明pinyin分词配置好了。

5,不足:

目前看在搜索完成后,高亮显示还有点问题,因为索引里面增加了很多拼音。

局限性,只能简单对比较段的内容进行分词,比如商品,电影,图书等,要是文字太长使用NGramTokenizer 分词就会增加一堆没用的pinyin。




推荐阅读
  • Lucene系列四:Lucene提供的分词器、IKAnalyze中文分词器集成、扩展 IKAnalyzer的停用词和新词
    一、Lucene提供的分词器StandardAnalyzer和SmartChineseAnalyzer1.新建一个测试Lucene提供的分词器的maven项目LuceneAnal ... [详细]
  • 本文详细介绍了 Spark 中的弹性分布式数据集(RDD)及其常见的操作方法,包括 union、intersection、cartesian、subtract、join、cogroup 等转换操作,以及 count、collect、reduce、take、foreach、first、saveAsTextFile 等行动操作。 ... [详细]
  • MySQL初级篇——字符串、日期时间、流程控制函数的相关应用
    文章目录:1.字符串函数2.日期时间函数2.1获取日期时间2.2日期与时间戳的转换2.3获取年月日、时分秒、星期数、天数等函数2.4时间和秒钟的转换2. ... [详细]
  • 部署solr建立nutch索引
    2019独角兽企业重金招聘Python工程师标准接着上篇nutch1.4的部署应用,我们来部署一下solr,solr是对lucene进行了封装的企 ... [详细]
  • 本文详细介绍了如何使用JavaScript实现面部交换功能,包括基本原理和具体实现步骤。 ... [详细]
  • 一个建表一个执行crud操作建表代码importandroid.content.Context;importandroid.database.sqlite.SQLiteDat ... [详细]
  • Hadoop的文件操作位于包org.apache.hadoop.fs里面,能够进行新建、删除、修改等操作。比较重要的几个类:(1)Configurati ... [详细]
  • [转]doc,ppt,xls文件格式转PDF格式http:blog.csdn.netlee353086articledetails7920355确实好用。需要注意的是#import ... [详细]
  • 如何在Java中使用DButils类
    这期内容当中小编将会给大家带来有关如何在Java中使用DButils类,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。D ... [详细]
  • 在JavaWeb开发中,文件上传是一个常见的需求。无论是通过表单还是其他方式上传文件,都必须使用POST请求。前端部分通常采用HTML表单来实现文件选择和提交功能。后端则利用Apache Commons FileUpload库来处理上传的文件,该库提供了强大的文件解析和存储能力,能够高效地处理各种文件类型。此外,为了提高系统的安全性和稳定性,还需要对上传文件的大小、格式等进行严格的校验和限制。 ... [详细]
  • 在PHP中,高效地分割字符串是一项常见的需求。本文探讨了多种技术,用于在特定字符(如“或”)后进行字符串分割。通过使用正则表达式和内置函数,可以实现更加灵活和高效的字符串处理。例如,可以使用 `preg_split` 函数来实现这一目标,该函数允许指定复杂的分隔符模式,从而提高代码的可读性和性能。此外,文章还介绍了如何优化分割操作以减少内存消耗和提高执行速度。 ... [详细]
  • FastDFS Nginx 扩展模块的源代码解析与技术剖析
    FastDFS Nginx 扩展模块的源代码解析与技术剖析 ... [详细]
  • “近年来最大计算机漏洞”被中国程序员发现!
    头条中国程序员,计算机漏洞头条(观察者网讯)据美联社12月11日报道,中国阿里云安全团队在Web服务器软件阿帕奇(Apache)下的开源日志组件Log4j内,发现一个漏洞Log4S ... [详细]
  • camel_使用Camel在来自不同来源的Solr中索引数据
    camelApacheSolr是建立在Lucene之上的“流行的,快速的开源企业搜索平台”。为了进行搜索(并查找结果),通常需要从不同的源(例如内容管理 ... [详细]
  • 理解和应用HTTP请求中的转发与重定向机制
    在HTTP请求处理过程中,客户端发送请求(通常简称为req),服务器进行相应处理后返回响应(通常简称为res)。理解和应用客户端的转发与重定向机制是前端开发的重要内容。这两种机制在Web开发中具有关键作用,能够有效管理和优化用户请求的处理流程。转发机制允许服务器内部将请求传递给另一个资源,而重定向则指示客户端向新的URL发起新的请求,从而实现页面跳转或资源更新。掌握这些技术有助于提升应用的性能和用户体验。 ... [详细]
author-avatar
云思逸
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有