原因
前段时间,在开发网站时需要搜索功能。因为项目需求的原因,需要使用Lucene,不过在使用的过程中,遇到了一个特别的需求。当前我们的数据库,主要有三种数据,就是英繁简三种语言版本的数据,英文一般都有数据,但是繁简就不一定了,繁简体有可能会有空的数据出现,为了给用户更好的搜索体验,当用户输入简体数据,但数据库只有繁体数据时,需要实现就算数据库中简体没有数据,只要繁体有匹配的数据,都能显示结果给用户。
解决方案
代码不是太复杂,主要是实现当中的set方法,利用以前我们所写的i18n功能,实现繁简体的转换之后,再进行索引,例如如果检测到繁体语言版本没有数据,则将繁体数据进行i18n转换,反之亦然。
参考资料
http://www.hibernate.org/subprojects/search.html
网上有人翻译了HibernateSearch的技术文档,虽然翻译得不是特别好,但还过得去,可以作一个参考:
http://sin90lzc.iteye.com/category/160975
前段时间,在开发网站时需要搜索功能。因为项目需求的原因,需要使用Lucene,不过在使用的过程中,遇到了一个特别的需求。当前我们的数据库,主要有三种数据,就是英繁简三种语言版本的数据,英文一般都有数据,但是繁简就不一定了,繁简体有可能会有空的数据出现,为了给用户更好的搜索体验,当用户输入简体数据,但数据库只有繁体数据时,需要实现就算数据库中简体没有数据,只要繁体有匹配的数据,都能显示结果给用户。
解决方案
由于我们在使用Lucene的同时,也引入了HibernateSearch。HibernateSearch为JPA提供了良好的支持,所以要解决以上的问题,我们可以借助它的桥接器功能。通过相关的文档,我们了解到HibernateSearch提供了一个叫FieldBridge的接口,利用这个接口,可以用来对字段进行自定义索引,从而解决繁简体的问题。
public class I18nFieldBridge
implements FieldBridge, TwoWayFieldBridge
{
/**
* 得到指定的值.
* @param name 字段名
* @param document document对象
* @return 字段的值
*/
public Object get(String name, Document document)
{
final Field field = document.getField(name);
return field.stringValue();
}
/**
* 设置指定的值.
* @param name 字段名
* @param value 要设置的值
* @param document document对象
* @param luceneOptions Lucene的选项值
*/
public void set(String name, Object value, Document document, LuceneOptions luceneOptions)
{
final String stringValue = (String) value;
if (stringValue == null)
{
if (name.startsWith("sC"))
{
final String fieldName = name.substring(2, name.length());
final Field field = document.getField("tC" + fieldName);
if (field != null)
{
final String indexedString = field.stringValue();
final String i18nIndexedString = CharSetUtil.convertCharSet(indexedString,
CharSetUtil.TRADITIONAL_CHINESE_CHARSET_HK, WordSetType.DEFAULT);
luceneOptions.addFieldToDocument(name, i18nIndexedString, document);
}
}
else
{
if (name.startsWith("tC"))
{
final String fieldName = name.substring(2, name.length());
final Field field = document.getField("sC" + fieldName);
if (field != null)
{
final String indexedString = field.stringValue();
final String i18nIndexedString = CharSetUtil.convertCharSet(indexedString,
CharSetUtil.SIMPLIFIED_CHINESE_CHARSET, WordSetType.DEFAULT);
luceneOptions.addFieldToDocument(name, i18nIndexedString, document);
}
}
else
{
luceneOptions.addFieldToDocument(name, stringValue, document);
}
}
}
else
{
luceneOptions.addFieldToDocument(name, getAllLanguageMessage(name, document, stringValue), document);
}
}
/**
* 得到所有语言版本的信息。
* @param name 字段名
* @param document document对象
* @return 语言版本的信息
*/
private String getAllLanguageMessage(String name, Document document, String stringValue)
{
final StringBuffer buffer = new StringBuffer();
buffer.append(stringValue);
final String i18nTCIndexedString = CharSetUtil.convertCharSet(stringValue,
CharSetUtil.TRADITIONAL_CHINESE_CHARSET_HK, WordSetType.DEFAULT);
buffer.append(i18nTCIndexedString);
final String i18nSCIndexedString = CharSetUtil.convertCharSet(stringValue, CharSetUtil.SIMPLIFIED_CHINESE_CHARSET,
WordSetType.DEFAULT);
buffer.append(i18nSCIndexedString);
final String message = buffer.toString();
return message;
}
/**
* 转换为字符串.
* @param value 要转换的对象
* @return 转换后的字符串
*/
public String objectToString(Object value)
{
final String originalValue = value.toString();
return originalValue;
}
}
代码不是太复杂,主要是实现当中的set方法,利用以前我们所写的i18n功能,实现繁简体的转换之后,再进行索引,例如如果检测到繁体语言版本没有数据,则将繁体数据进行i18n转换,反之亦然。
参考资料
http://www.hibernate.org/subprojects/search.html
网上有人翻译了HibernateSearch的技术文档,虽然翻译得不是特别好,但还过得去,可以作一个参考:
http://sin90lzc.iteye.com/category/160975