记录下最近两天散仙在工作中遇到的有关Pig0.12.0和Solr4.10.2一些问题总共有3个如下 1问题一 如何Pig中使用ASCII和十六进制hexadecimal的分隔符进行加载和切分数据 注意关于这个问题在Pig中会反应到2个场景中 第一 在Pig加载load数据时候 。 第二 在Pig处理split或则正则截取数据的时候。 先稍微说下为啥使用十六进制的字段分隔符而不是我们常见的空格逗号冒号分号#号等这些字符虽然也可以使用但是如果我们数据中有和这些符号冲突的数据那么在解析时就会发生一些出人意料的Bug所以为了保险起见选用肉眼不可读的十六进制的数据是一个不错的选择当然这也是针对场景来说的看情况决定。 关于详细的ASCII和十六进制二进制八进制十进制的文档介绍请参考百科全书。 下面继续回到正题本例中我们的数据格式是这样存储的
Java代码
每行一条记录,UTF-8编码
每条记录都包括字段名和字段内容
字段之间用ascii码1分隔
字段名与内容之间用ascii码2分隔
每行一条记录,UTF-8编码每条记录都包括字段名和字段内容字段之间用ascii码1分隔字段名与内容之间用ascii码2分隔一个在eclipse中的小例子如下
Java代码
public static void main(String[] args) {
//注意\1和\2在我们的IDE中NotePad++中Linux的终端设备的界面中都会呈现不同的
//显示方式大家可以在维基百科中详细了解下
//数据示例
String s="prod_cate_disp_id019";
//split规则
String ss[]=s.split("\2");
for(String st:ss){
System.out.println(st);
}
}
public static void main(String[] args) { //注意\1和\2在我们的IDE中NotePad++中Linux的终端设备的界面中都会呈现不同的 //显示方式大家可以在维基百科中详细了解下 //数据示例 String s="prod_cate_disp_id019"; //split规则 String ss[]=s.split("\2"); for(String st:ss){ System.out.println(st); } }关于load函数加载时支持的分隔符类型大家可以参考官网的 下面看在Pig脚本的代码
Java代码
--Hadoop技术交流群415886155
/*Pig支持的分隔符包括
1,任意字符串
2,任意转义字符
3dec的字符\\u001 或者 \\u002
4十六进行字符 \\x0A \\x0B
*/
--注意这个load时的分隔符代表ASCII的1作为Pig里面的dec直接解析方式
a = load '/tmp/dongliang/20150401/20150301/tmp_search_keywords_cate_stat/' using PigStorage('\\u001') ;
/**
注意下面的分割符^B这个符号是脱元字符只会在终端设备上
显示这个符号代表ASCII的2
*/
a = foreach a generate REGEX_EXTRACT ($0, '(.*)^B(.*)', 2) as time ,
REGEX_EXTRACT ($1, '(.*)^B(.*)', 2) as kw ,
REGEX_EXTRACT ($2, '(.*)^B(.*)', 2) as ic ,
REGEX_EXTRACT ($3, '(.*)^B(.*)', 2) as cid,
REGEX_EXTRACT ($4, '(.*)^B(.*)', 2) as cname,
REGEX_EXTRACT ($5, '(.*)^B(.*)', 2) as pname,
REGEX_EXTRACT ($6, '(.*)^B(.*)', 2) as snt,
REGEX_EXTRACT ($7, '(.*)^B(.*)', 2) as cnt,
REGEX_EXTRACT ($8, '(.*)^B(.*)', 2) as fnt,
REGEX_EXTRACT ($9, '(.*)^B(.*)', 2) as ant,
REGEX_EXTRACT ($10, '(.*)^B(.*)', 2) as pnt ;
--获取字符串长度
a = foreach a generate SIZE(cid) as len;
--按长度分组
b = group a by len;
--统计各个长度下的数量
c = foreach b generate group, COUNT($1);
--输出打印
dump c;
--Hadoop技术交流群415886155/*Pig支持的分隔符包括1,任意字符串2,任意转义字符3dec的字符\\u001 或者 \\u0024十六进行字符 \\x0A \\x0B*/--注意这个load时的分隔符代表ASCII的1作为Pig里面的dec直接解析方式a = load '/tmp/dongliang/20150401/20150301/tmp_search_keywords_cate_stat/' using PigStorage('\\u001') ;/**注意下面的分割符^B这个符号是脱元字符只会在终端设备上显示这个符号代表ASCII的2*/a = foreach a generate REGEX_EXTRACT ($0, '(.*)^B(.*)', 2) as time , REGEX_EXTRACT ($1, '(.*)^B(.*)', 2) as kw , REGEX_EXTRACT ($2, '(.*)^B(.*)', 2) as ic , REGEX_EXTRACT ($3, '(.*)^B(.*)', 2) as cid, REGEX_EXTRACT ($4, '(.*)^B(.*)', 2) as cname, REGEX_EXTRACT ($5, '(.*)^B(.*)', 2) as pname, REGEX_EXTRACT ($6, '(.*)^B(.*)', 2) as snt, REGEX_EXTRACT ($7, '(.*)^B(.*)', 2) as cnt, REGEX_EXTRACT ($8, '(.*)^B(.*)', 2) as fnt, REGEX_EXTRACT ($9, '(.*)^B(.*)', 2) as ant, REGEX_EXTRACT ($10, '(.*)^B(.*)', 2) as pnt ;--获取字符串长度a = foreach a generate SIZE(cid) as len;--按长度分组b = group a by len;--统计各个长度下的数量c = foreach b generate group, COUNT($1);--输出打印dump c;2问题二如何在Apache Solr中查询某个不分词的field的长度有多少个记录 Solr里面并没有直接提供这样类似JAVA里的lenth这样的函数或者Pig里面的SIZE这样的函数那么我们应该如何查询呢 Solr虽然不直接支持这样的查询但是我们可以通过正则查询来变相的实现这个目的用法如下 1查询固定长度 cid:/.{6}/ 只过滤长度为6的记录 2查询范围长度 cid:/.{6,9}/ 只过滤长度6到9的记录 3查询最少多少长度以上的cid:/.{6}.*/ 长度最少为6的 3问题三在使用Pig+MapReduce向Solr中批量添加索引时发现无任何错误异常但是索引里却没任何数据? 这是一个比较诡异的问题本来散仙觉得应该是程序出问题了但是后来发现同样的代码向另外一个collection里添加数据就很正常查看solr的log发现里面打印的一些信息如下
Java代码
INFO - 2015-04-01 21:08:36.097; org.apache.solr.update.DirectUpdateHandler2; start commit{,optimize=false,openSearcher=true,waitSearcher=true,expungeDeletes=false,softCommit=false,prepareCommit=false}
INFO - 2015-04-01 21:08:36.098; org.apache.solr.update.DirectUpdateHandler2; No uncommitted changes. Skipping IW.commit.
INFO - 2015-04-01 21:08:36.101; org.apache.solr.core.SolrCore; SolrIndexSearcher has not changed - not re-opening: org.apache.solr.search.SolrIndexSearcher
INFO - 2015-04-01 21:08:36.102; org.apache.solr.update.DirectUpdateHandler2; end_commit_flush
INFO - 2015-04-01 21:08:36.097; org.apache.solr.update.DirectUpdateHandler2; start commit{,optimize=false,openSearcher=true,waitSearcher=true,expungeDeletes=false,softCommit=false,prepareCommit=false}INFO - 2015-04-01 21:08:36.098; org.apache.solr.update.DirectUpdateHandler2; No uncommitted changes. Skipping IW.commit.INFO - 2015-04-01 21:08:36.101; org.apache.solr.core.SolrCore; SolrIndexSearcher has not changed - not re-opening: org.apache.solr.search.SolrIndexSearcherINFO - 2015-04-01 21:08:36.102; org.apache.solr.update.DirectUpdateHandler2; end_commit_flush解释下上面的信息的意思大概就是说在数据索引完了但是没有发现有commit的数据所以跳过commit这一点在程序跑的时候是非常奇怪的因为数据源HDFS里最少有110万的数据怎么会没有数据呢 然后散仙通过谷歌搜索发现也有人发现类似的奇怪情况无任何异常的情况下重建索引成功却在索引里没有看见任何数据而且最为疑惑的是这几个网上已经有的案例竟然没有一个有解决方案。 没办法了只好再次查看程序这一次散仙把中间处理好需要建索引的数据给打印出来看一下到底什么情况结果打印出来的都是一行行空数据原来在使用正则截取数据时原来的分隔符失效了所以导致截取不到数据这下问题基本定位了solr索引里没有数据肯定是因为本来就没有数据提交导致的那个奇怪的log发生结果在散仙把这个bug修复之后再次重建索引发现这次果然成功了在Solr中也能正常查询到数据。如果你也发生了类似的情况请首先确保你能正确的获取到数据不论是从远程读取的还是解析wordexcel或者txt里面的数据都要首先确定能够正确的把数据解析出来然后如果还是没建成功可根据solr的log或者抛出的异常提示进行修复 。