86565656 发表于 2015-7-17 11:38:28

solr 之 transformer

  1. 自己的例子,去掉手尾的半角空格:

  2. 然后 export->java->JAR file 即可打好一个jar包,起个名字叫ltz.jar包
  3. 把此jar包导入到solr,然后配置一下data-config.xml即可

  4. 最后处理结果如下

  5. 详细讲解:

ransformer
  每一条从数据库中取得的数据能够被直接处理掉,或者通过它创建一个全新的域,它设置能够返回多行数据。配置文件必须像下面那样设置。







注意-- trasformer的值必须是一个可以使用的classname。如果class包是'org.apache.solr.handler.dataimport' ,包名可以被忽略。solr.也是可以使用的,如果这个class在solr的一个包下的话。这个规则适应所有的可插入的类,像 DataSource、EntityProcessor、Evaluator。
  类Foo必须继承抽象类org.apache.solr.hander.dataimport.Transformer.这个类只有一个抽 象方法。
  transformer这个属性可以有多个transformers() (比 如 transformer="foo.X,foo.Y" ) 之间用逗号隔开。 transformers 会形成一条处理链。它们将会按照它们的排列顺序起作用。

public abstract class Transformer {

/**

* The input is a row of data and the output has to be a new row.

*

* @param context The current context

* @param row   A row of data

* @return The changed data. It must be a Map if it returns

*         only one row or if there are multiple rows to be returned it must

*         be a List
  >

*/

public abstract Object transformRow(Map row, Context context);

}
  Context 是一个抽象的类,它提供上下文关系,这可能在处理数据的时候要用到。
  另外,类Foo,可以选择不不实现这个抽象类,而只需要下面这个方法
  public Object transformRow(Map row)
  So there is no compile-time dependency on the DataImportHandler API
  它的配置是灵活的。它允许用户向标签entity和field提供任意的属性。tool将会读取数据,并将它传给实现类。如果 Transformer需要额外的的信息,它可以从context中取得。

正则表达式转换器
  tool它提供了一个内嵌的转换器,叫做正则表达式转换器。它可以使用正则表达式从原数据中解析出我们想要的值。org.apache.solr.handler.dataimport.RegexTransformer 是它的名字. 因为它属于默认的包,所以它的包名是可以被忽略的。
  例子:



... />












  

属性
  RegexTransfromer只对属性中有regex或者splitBy的域起作用。所有的属性我们列在下面。


[*]  regex : 这是要匹配的正则表达式。regex和splitBy两者必有其一。如果没有,这个域将不会被正则表达式转换器处理。

[*]  sourceColName : 正则表达式起作用的列。. 如果这个这个属性不存在,那么source将等同域target。

[*]  splitBy : 如果正则表达式,是被用来分割一个字符串以获得多个值,那么使用这个。

[*]  replaceWith : 跟 属性regex一起使用。相当于我们平常使用的方法new String().replaceAll(, )

  这里,属性‘regex’和‘sourceColName’是转换器自定义的属性。它从resultSet中读取域‘full_name’的值,然 后转换它,并将结果分别传给‘firstName’和‘lastName’。所以,尽管查询结果只返回一列“full_name”,但solr document依然可以获得额外的两个域“firstName”和‘lastName’。
  域'emailids'是一个用逗号分隔着的值。 所以,我们最终可以从emailids得到一个以上的emial id。mailid 在solr中应该被定义为多值的。

脚本转换器
  你可以使用javascript 或者其他的 脚本语言来写转换器,只要java支持这种脚本。在这里我们应该使用java 6.









....








  


[*]  你可以在dataConfig结点中设置script 标签。默认的语言是javascript。你当然可以使用另外一种语言,你可以通过script标签中的属性language去设置它。(必须有 java6的支持)。

[*]  你可以写任意多的转换函数。每个函数必须接受一个相当于 Map的row变量,然后要返回一个row。(转换以后)

[*]  通过在实体中指定 transformer=“script:”来使一个实体使用脚本函数。

[*]  在上面的data-config中,对于结果中返回的实体e的每一个行,javascript函数都将被执行一次。

[*]  执行机制跟一个java的转换器是一样的。在Transformer 中有两个参数 (transformRow(Map,Context ))。在javascript中,第二个参数被忽略了,但它一样是起作用的。


日期格式转换器
  这里有一个内嵌的转换器,叫做DateFormatTransformer(日期格式转换器) ,这个在将字符型时间转换成java.util.Date的类型的时候是很有用的。




属性
  日期格式转换器只对带有属性“dateTimeFormat”的域才起作用。其他属性如下所示。


[*]  dateTimeFormat : 转换使用的格式。这个必须服从java的SimpleDateformat。

[*]  sourceColName : 要使用日期转换的列。如果没有设定这个值,那么源列跟目标域的名称是一样的。

  上面的域的定义在RSS例子中有使用,以转换RSS种子项中的时间格式。

数字格式转换器
  能将一个字符串转换成一个数字,使用的是java中类NumberFormat。例子:


  默认情况下,类Numberformat使用系统的本地格式去转换一个字符串,如果你需要指定一个不同的本地类型的话,你可以像下面这样指定。例 子:




属性
  数字格式转换器 只对那些带有属性“formatStyle”的域有用。


[*]  formatStyle : 解析这个域所需要的格式。这个属性的值必须是(number|percent|integer|currency)中的一个。可以参考 javaNumberFormat .

[*]  sourceColName : 要使用数字转换的列。如果没有设定这个值,那么源列跟目标域的名称是一样的。

[*]  locale : 要转换的字符串所使用的国际化格式。如果没有设定这个值,它的默认值是系统的国际化格式。它的值必须是language-country。例如 en-US。


模板转换器
  使用DataImportHandler中强大的模板引擎来创建或者设定一个域的值。例如:





...






  这里模板的规则跟‘query’、‘url’的规则是一样的。它主要能帮我们将多个值连到一起,或者忘域值注入其他的字符。这个转换器只对拥有属性 ‘template’的域起作用。

属性


[*]  template : 模板字符串。上面的例子中有两个占位符,‘${e.name}和${eparent.surname}’。 In the above example there are two placeholders '${e.name}' and '${eparent.surname}' . 两个值都必须存在,否则这个模板将不会起作用。


自定义模板转换器
  如果你需要在将数据送给solr之前,对数据进行一些处理,你可以写一个你自己的转换器。让我们来看一个例子。在我们的schema中我们有一个单 值的域叫做‘artistName’,类型是String。这个域的值包含了多个单词,例如‘Celine Dion’,这里有一个问题 ,这个值包含一些开头空格和结尾空格,这些空格不是我们想要的。solr的WhitespaceAnalyze在这里用不上,因为,我们并不想把这个字符 串切词了。一个可以选择的解决方案就是自己写一个TrimTransformer。

一个简单的TrimTransformer

package foo;

public class TrimTransformer    {

public Object transformRow(Map row)   {

String artist = row.get("artist");

if (artist != null)            

row.put("ar", artist.trim());



return row;

}

}


  不需要去继承任何类。这个类只需要有transformRow 方法,就像上面的那样。DataImportHandler会自动辨别它,并使用反射机制来调用它。你可以在你的data-config.xml文件中这 样来设置:










一个通用的TrimTransformer
  假设,你想写一个通用的TrimTransformer,这样你就不用将要处理的列写在的代码里面。这里,我们需要在data- config.xml中设一个标记来表示这个域是否要应用这个转换器。










  现在,你需要去继承 Transformer这 个抽象类,并使用Context中的API来获得实体中的域,并获得域中的属性,检查标记有没有被设值。

package foo;

public class TrimTransformer extends Transformer      {



public Map transformRow(Map row, Context context) {

List
  > fields = context.getAllEntityFields();

for (Map field : fields) {

// Check if this field has trim="true" specified in the data-config.xml

String trim = field.get("trim");

if ("true".equals(trim))      {

// Apply trim on this field

String columnName = field.get("column");

// Get this field's value from the current row

String value = row.get(columnName);

// Trim and put the updated value back in the current row

if (value != null)

row.put(columnName, value.trim());

}

}

return row;

}

}
  如果域是多值的,那么返回值将会是一个list而不是单单一个对象,而且需要被恰当的处理。你可以将DataImprotHandler打包成一个 jar包,然后再扩展Transformer和Context。
  
页: [1]
查看完整版本: solr 之 transformer