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

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 < str.length(); 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 < allPinYin.length(); 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分开配置:

		<!-- standard_text.标准分词.创建使用pinyin分词,搜索不使用. -->
		<fieldType name="standard_text" class="solr.TextField"
			positionIncrementGap="100">
			<analyzer type="index">
				<tokenizer class="com.freewebsys.index.analysis.PinyinTokenizerFactory" />
				<filter class="solr.LowerCaseFilterFactory" />
				<filter class="solr.WordDelimiterFilterFactory"
					generateWordParts="1" generateNumberParts="1" catenateWords="0"
					catenateNumbers="1" catenateAll="0" splitOnCaseChange="1" />
			</analyzer>
			<analyzer type="query">
				<tokenizer class="solr.StandardTokenizerFactory" />
			</analyzer>
		</fieldType>

4,使用分词效果:

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

5,不足:

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

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

时间: 2024-07-31 17:21:43

使用solr实现pinyin分词,针对短词搜索,比如电影搜索的相关文章

浅谈热门关键词与短词都有哪些区别

今天和大家来交流一下热词和短词的区别,如果有说得不好的地方,请大家指点,有一些站朋友这样认为,一些热门关键词不好做,竞争很激烈, 既然不好做,那就不要去做了! 笔者暂时不谈这个问题. 很多站长朋友都将热门关键词理解为搜索的人多的关键词,比如百度等搜索引擎提到热词排行榜之类,这里的热词纯粹是从搜索的次数来判断.而短头是SEO行业的一个专业术语,特指那些搜索量高.竞争的网站多且跟企业或个人要做的产品或服务不相关的关键词.能看到一个共性是热词和短头都具有很高的搜索量,但是对于竞争度方面和相关度方面根本

solr进阶: 如何定制搜索服务,扩展搜索逻辑

前两天发了篇"剖析solr实用性",主要黑了solr建索引让我觉得不舒服,还黑了solr只是个通用的丢入了servlet容器里的简单服务,事实证明我错了.这篇博客我要纠正并回答那篇博客里自己总结的问题:如何定制solr实现自己的搜索服务. solr是一个可扩展的服务,我们可以添加自己的包和类,在solr已经实现的default处理逻辑之上,再添加我们自己的搜索逻辑.实现手段就是继承solr的基础类,重写或者改写新的Filter,Search Component以及Request Han

c#-求代码,用C# 实现单个词的位置的搜索

问题描述 求代码,用C# 实现单个词的位置的搜索 500C C# 实现单个词的位置的搜索,即手动选择一个词语,然后在文档里面搜索其所在的位置,搜索到了之后标记,在文档的最后面返回其位置,如页码数.. 解决方案 参考:http://bbs.csdn.net/topics/330160450 请勿重复发帖. 解决方案二: 问答以讨论问题为主,你先动手做,遇到问题再问.重复发帖并不能收获更多的答案.与其这样不如把问题问明确. 解决方案三: C#文件查找(按内容.文件名称查找) 解决方案四: priva

Solr/Lucene日志分析-查询热点词-脚本工具

solr/lucene 在中文搜索使用中,会输出非常多的类似下面的内容: 2012-04-24 00:00:01,396 INFO [org.apache.solr.core.SolrCore] - [XXXX-0] webapp=null path=/select params={q=status:0+AND+(img_file_id:(++12333018751568476))&timeAllowed=2000sort=gmtcreate+desc&rows=60&start=

solr 实现 中文分词,IK Analyzer

solr默认是不支持中文分词的,这样就需要我们手工配置中文分词器,在这里我们选用IK Analyzer中文分词器. IK Analyzer下载地址:https://code.google.com/p/ik-analyzer/downloads/list 如图:     默认大家已经下载并解压了solr,在这里我们使用solr 4.10.4版本 试验环境centos 6.5 ,JDK1.7 整合步骤 1:解压下载的IK Analyzer_2012_FF_hf1.zip压缩包,把IKAnalyzer

Solr配置中文分词器IKAnalyzer及增删改查调用

一.配置IKAnalyzer中文分词器 Solr 版本5.2.1 IKAnalyzer2012_u6.jar报错 ,用IKAnalyzer2012_FF_hf1.jar 替换可解决 解决lucene4.0与IKAnalyzer的冲突.解决Exception in thread "main" java.lang.VerifyError: class org.wltea.analyzer.lucene.IKAnalyzer overrides final method tokenStrea

Overture针对Google的竞争推地方搜索广告

中介交易 SEO诊断 淘宝客 云主机 技术大厅 DMNews纽约时间3月8日报道:Overture服务公司计划在未来的几个月内推出地方搜索广告项目,允许广告客户限制广告列表在规定的地域内显示,同时也可以使无站点广告客户加入这一推广项目. Overture地方搜索部门总经理GeoffStevens在本月4日举行的搜索引擎战略会议上介绍说,这一系统将使得地方广告客户与邻近地域消费客户匹配起来,Overture的广告客户可以把自己的广告列表定位于以一英里为半径的地域范围内限制显示,也可以按照邮政编码定

sql server 2005全文索引 记录筛选问题

问题描述 产品表product目前有记录20多万条,在productname(商品名称),summary(商品描述),intorduction(详细介绍)三个字段是建立全文索引,本人的开发及配置环境是windows2003sp2,vs.net2005sp1,sqlserver2005sp2,此三个字段都是英文的,按英文的习惯要得到需要的西方结果集.现有以下问题,请大家帮忙看下.1:词意问题,针对一个词.如用户搜索的词是soft,则只查询和soft有关的记录,比如搜索结果中包含software是不

怎样让非常规关键词给网站带来流量

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断淘宝客 站长团购 云主机 技术大厅 最近有群友问网站的快照不稳定,收录时有时无,不知其原有!在探讨中我们发现他采用了刷流量的方法,让百度对该网站提出了警告.其实我都清楚,刷流量是黑帽手段,那为什么还有SEOer顶风作案呢?原因在于他们通过设置的关键词不能给网站带来流量,这样就让网站成为了"死站",对企业来说没有任何营销效果.就此,笔者小丹今天要和大家