transformer转换器
转换器可以操作有实体返回的文档中字段。一个转换器可以创建新的字段或者修改已有的字段。需要通过entity元素上添加transformer属性来告诉实体你的额导入操作将使用哪种转换器。transformer属性可以指定多个,多个属性使用逗号分隔。
<entity name="abcde" transformer="ClobTransformer,DateFormateTransformer"/>
除特殊情况外,transformer属性值必须包含完整包路径,除非类的包名是org.apache.solr.handler.dataimport,那么报名可以省略直接输入类名即可,或者如果该类术语solr源代码包中的类,那么属性值等于solr.<classname>也是可行的。这条规则适用于所有solr插件比如datasource,entityproessor,evaluator。
多个transformer转换器严格按照指定的顺序从左至右依次被执行,transformer转换器的一些转换规则参数通过为随后的field元素添加属性方式来指定。
<entity name="e" transformer="ClobTransformer"...>
<field column="hugeTextField" colb="true"/>
...
</entity>
1) RegexTransformer
Solr DIH 内置提供了一个RegexTransformer转换器,它使用正则表达式来剔除或操作Field的值。
- regex:指定应用到column或者sourceColName上的正则表达式。若replaceWith属性不存在,那么会提取每个正则匹配组的值并以list集合形式返回;
- sourceColName:正则表达式应用到的源列名,如果此属性未指定,那么源列和目标列将是同一个,即直接替换更新源列的值,而不是存储到一个新的目标列上;
- splitBy:用于对一个列的值按照分隔符进行分割返回一个ist;
- groupNames:此属性用于接收以逗号分隔的多个column名称,他依次对应正则表达式的每个匹配组,匹配组提取到的值会作为对应column的值,如果某些组没有对应的column,则会使用空格代替;
-
replaceWith:使用正则表达式对column的值进行替换,他等价于java里的String.replaceAll()
注意⚠️:只有当field配置了regex或者splitBy属性时,RegexTransformer转换器才会被激活使用。
<entity name="foo" transformer="RegexTransformer" query="select full_name, emailids from foo"/>
<field column="full_name"/>
<field column="firstName" regex="Mr(\w*)\b.*" sourceColName="full_name"/>
<field column="lastName" regex="Mr.*?\b(\w*)" sourceColName="full_name"/>
<!--另一种方法-->
<field column="full_name" regex="Mr(\w*)\b(.*)" groupNames="firstName,lastName"/>
<field column="mailid" splitBy="," sourceColName="emailids"/>
<entity>
2) ScriptTransformer
可以使用JavaScript或者其他Java支持的脚本语言来编写transformers,要使用这项功能前提是你必需使用JDK6或更高的版本。
例1:
<dataConfig>
<script>
<![CDATA[
function f1(row) {
row.put('message','Hello World!');
return row;
}]]>
</script>
<document>
<entity name="e" pk="id" transformer="script:f1" query="select * from x">
...
</entity>
</document>
</dataConfig>
例2:
<dataConfig>
<script>
<![CDATA[
function CategoryPieces(row) {
var pieces = row.get('category').split('/');
var arr = new java.util.ArrayList();
for (var i=0; i<pieces.length; i++) {
arr.add(pieces[i]);
}
row.put('categorypieces',arr);
row.remove('category');
return row;
}
]]>
</script>
<document>
<entity name="e" pk="id" transformer="script:CategoryPieces" query="select * from X">
...
</entity>
</document>
</dataConfig>
- 可以在dataConfig元素内部添加一个script标签,默认会被解析为Javascript。如果你需要使用其他脚本语言,你需要在script标签例通过language属性来指定,前提是Java6支持该脚本语言;
- 你可以使用脚本编写任何你想要实现的转换函数,每个转换函数需要强制接收一个row变量,该变量是一个类似Map<String,Object>的结构,在函数转换后你需要在返回一个row类型;
- 要移除某个entity,你可以在转换函数内部通过row.remove(keyname)来实现;
- 要为某个entity,你必需使用var arr = new java.util.ArrayList(),不能使用JavaScript里的Array数组类型;
- 使用脚本转换函数来穿件一个entity,你可以通过entity节点元素中指定transformer="script:<function-name>"来实现;
- 在上面的data-config配置中,query属性指定的SQL语句执行后返回的结果集中的每个row都会经过categorypieces函数进行转换,转换后生成的每个新entity缓存到entity="e"中;
- 脚本实现的转换函数在执行语义上讲,跟java实现transformer相同,java里该转换函数定义为transformRow(Map<String,Object>,Context context),其实你会第二个参数context即执行上下文对象,在脚本实现里,第二个参数虽然被忽略了,但并不影响执行;
3) DateFormatTransformer
此转换器用于将日期时间格式字符串类型转换成java.util.Date对象。当且仅当field元素添加了dataTimeFormat属性时,DateFormatTransformer转换器才会被激活启用。
<field column="date" xpath="/RDF/item/date"
dateTimeFormat="yyyy-MM-dd 'T' HH:mm:ss" locale="en"/>
- dateTimeFormat:用于指定需要转换的日期时间字符串的格式,他完全遵循java里的SimpleDateFormet类型的日期格式规范;
- sourceColName:dateTimeFormat参数将被应用到sourceColName属性指定的列上,若此属性为指定,那么源列和目标列将是同一个,即转换函数会替换更新源列的值;
-
locale:用于指定本地所属地区,若未指定,对于solr4.1版本或者更高版本会使用root local作为默认值,solr4.1版本之前会使用当前机器的默认local;
4) NumberFormatTransformer
此转换器用于将一个字符串转换成数字。
<field column="price" formatStyle="number"/>
- formatStyle:用于指定转换字符串的数字格式,该属性值必须是(number|percent|integer|currency)其中之一,它完全遵循java里的NumberFormat类的数字格式规范;
- sourceColName:formatStyle参数将被应用到sourceColName属性指定到列上,若此属性未指定,那么源列和目标列将是同一个,即转换函数会替换更新源列的值;
-
locale: 用于指定本地所属地区,若未指定,对于solr4.1版本或更高本本会使用root local作为默认值,solr4.1版本使用当前机器的默认local;
5) TemplateTransformer
此转换器用于根据一个静态的字符串模版来生成一个新的field或者更新一个field的值。
<entity name="e" transformer="TemplateTransformer"...>
<field column="namedesc" template="hello${e.name},${eparent.surname}"/>
...
</entity>
-
template:用于指定模版字符串。上述栗子中使用了
{eparent.surname}两个占位符参数。
6) HTMLStripTransformer
此转换器用于去除HTML标签只保留下纯文本,当你在处理HTML文件内容时,可能只关心标签之间的文本内容,此时HTMLStripTransformer就派上用场了。此转换器内部是通过org.apache.solr.analysis.HTMLStripReader类来实现该功能。
<entity name="e" transformer="HTMLStripTransformer" ...>
<field column="htmlText" stripHTML="true"/>
...
</entity>
- stripHTML: Boolean值,设置为true即表示启用HTMLStripTransformer功能。
7) ClobTransformer
此转换器用于处理将关系型数据库里的Clob数据类型转换成String。当你读取数据库表数据时,若某个字段的类型为Clob类型,此时ClobTransformer转换器就显得十分有用。
<entity name="e" transformer="ClobTransformer" ...>
<field column="hugeTextField" clob="true"/>
...
</entity>
- clob:Boolean值,设置为true即表示启用ClobTransformer功能;
- sourceColName:表示ClobTransformer处理的源列名,若此属性未指定,那么源列和目标列将是同一个,即转换函数会替换更新源列的值;
8) LogTransformer
此转换器用于记录日志数据,可以打印到控制台或者写入日志文件中。与其他转换器不同的是,此转换器不需要作用域任何field上,所以他的属性是直接配置在entity上到。可选日志级别有trace,debug,info,warn,error;
<entity ...
transformer="LogTransformer" logTemplate="The name is ${e.name}" logLevel="debug"> ...
</entity>
9) 自定义Transformer转换器
如果solr内置提供的这些转换器仍然无法满足你的需求时,你可以自定义Transformer转换器。
举个例子:假设你的schema中有一个string类型的单值域artistName,值域可以包含多个单词比如“Celine Dion”,但是这里会有一个问题,你的数据开头和结尾可能会包含空格,由于这里使用的是string类型,所以solr提供的WhitespaceAnalyzer分词器将无法使用,一种解决方法就是使用自定义Transformer转换器实现TrimTransformer来完成头尾空格字符的去除。
package foo;
public class TrimTransformer {
public Onject transformerRow(Map<String,Object> row) {
String artistName = row.get("artistName");
if(artistName != null) {
row.put("ar", artistName.trim());
}
return row;
}
}
你不需要继承任何类,你只需要简单写一个普通类,然后在该类内部定一个transformRow函数,该函数声明必须如上述代码所示。
当然你也可以继承抽象类org.apache.solr.handler.dataimport.Transformer来实现。
编写完毕后你需要将其打包成jar,将jar包复制到core的lib目录下,然后就可以在data-config.xml配置文件中引用你自定义的transformer转换器了。
<entity name="artist" query="..." transformer="foo.TrimTransformer">
<field column="artistName"/>
</entity>
在上述自定义Transformer代码中,我们column列名是硬编码在代码中的,从而导致这个自定义Transformer转换器无法达到通用的效果。此时你需要在data-config.xml的field元素上自定义一个标识为属性,然后需要继承org.apache.solr.handler.dataimport.Transformer抽象类,重写其transformRow函数,根据函数的第二个参数context对象,你可以获取到entity声明的所有field,通过自定义的标识为属性来动态定位field,从而解决了column名称硬编码的问题。
package foo;
public class TrimTransformer extends Transformer {
public Map<String, Object> transformRow(Map<String,Object> row, Context context) {
List<Map<String,String> fields = context.getAllEntityFields();
for (Map<String,String> field:fields){
//检查data-config.xml里的field元素上是否声明trim属性
String trim = field.get("trim");
if ("true".equals(trim)){
//获取当前列名
String columnName = field.get(DataImporter.COLUMN);
//获取当前列值
Object value = field.get(columnName);
//去空格并将更新后的值在赋值给当前行
if(value!=null) {
row.put(columnName,value.toString().trim());
}
}
return row;
}
}
}
想要继承transformer抽象类,需要导入apache-solr-dataimporthandler.jar。
网友评论