`
weitao1026
  • 浏览: 993861 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论
阅读更多



GMV(一定时间内的成交总额)是一个衡量电商网站营业收入的一项重要指标,例如淘宝,京东都有这样的衡量标准,感兴趣的朋友可以自己科普下这方面的概念知识。

当然散仙今天,并不是来解释概念的,而是记录下最近工作的一些东西,原来我们平台的GMV只有一个总的成交金额,并没有细分到各个系统的GMV的比重,比如搜索端,推荐端,移动端等等。

通过细粒度的分析各个系统所占的比重,对于指导各个系统完善和发展有一定的重要意义,这里不就深说了,下面先来看下散仙分析的搜索gmv的数据布局方式。


(1)Hadoop集群上,存储了一些非核心的数据,比如访问数据,点击数据,购物车数据,下单数据(这个是从数据库里每天同步到HDFS上的,算是备份吧)
(2)Oracle数据库中,存储了订单信息,交易信息,商品信息,支付信息等一些电商的核心数据

其实关于gmv的计算方式,在我们oracle库里,以及有一个存储过程封装了复杂的细节的处理,包括运费,折扣,不同国家,不同地域,信用用户,等等,在使用时候,只需要传入一个订单编号即可,计算出本单的gmv成交金额。


这样以来的,按照目前的数据情况,订单编号是从Hadoop集群上,一直是从搜索,点击,添加购物车,下单计算出来的,然后获取的对应的订单编号,注意这个过程中,是需要全程去爬虫数据的,因为还要算最终的GMV成交额,所以需要找到一定时期内的订单号,然后通过调用在oracle库的封装好的函数,计算出gmv,这样以来,就能够比较细跟踪各个阶段运行轨迹和成交额。

ok,业务上的分析大致如此,下面就看下,技术上如何实现,其实就是需要Pig的一个自定义UDF函数,在遍历每一行的recoder时,去查询oracle只读库,获取gmv的值,并将最终结果存储起来,以图形化方式展示。

Pig里面对UDF函数非常丰富,比较常用的是转化函数和加载存储函数,这一点在Hive里,也是如此,之前的文章中,散仙介绍过,通过自定义UDF将pig分析的结果直接存储到数据库或索引中,便于检索和发挥不同框架之间的组合优势。

核心代码如下:

Java代码 复制代码 收藏代码
  1. package com.pig.dhgate.getgvmbyrfxno;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.pig.EvalFunc;  
  6. import org.apache.pig.data.Tuple;  
  7. import org.slf4j.Logger;  
  8. import org.slf4j.LoggerFactory;  
  9. /** 
  10.  * 自定义Pig UDF实现查询db计算gmv 
  11.  * **/  
  12. public class GetGmvByRfxno extends EvalFunc<Double> {  
  13.     /**日志对象*/  
  14.     static Logger log =LoggerFactory.getLogger(GetGmvByRfxno.class);  
  15.     /**数据库工具类*/  
  16.     DBTools dbtools=new DBTools();  
  17.       
  18.     @Override  
  19.     public Double exec(Tuple input) throws IOException {  
  20.           
  21.         if(input!=null&&input.size()!=0){  
  22.             //获取传入的订单号  
  23.             String rfxno =(String)input.get(0);  
  24.             //通过db类,查询对应的gmv并返回  
  25.             double gmv=dbtools.getGmvByRfxno(rfxno);  
  26.             return gmv;  
  27.         }else{  
  28.             //对null,空值,一律按0处理  
  29.             return 0.00;  
  30.         }  
  31.     }  
  32. }  
package com.pig.dhgate.getgvmbyrfxno;

import java.io.IOException;

import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 自定义Pig UDF实现查询db计算gmv
 * **/
public class GetGmvByRfxno extends EvalFunc<Double> {
	/**日志对象*/
	static Logger log =LoggerFactory.getLogger(GetGmvByRfxno.class);
	/**数据库工具类*/
	DBTools dbtools=new DBTools();
	
	@Override
	public Double exec(Tuple input) throws IOException {
		
		if(input!=null&&input.size()!=0){
			//获取传入的订单号
			String rfxno =(String)input.get(0);
			//通过db类,查询对应的gmv并返回
			double gmv=dbtools.getGmvByRfxno(rfxno);
			return gmv;
		}else{
			//对null,空值,一律按0处理
			return 0.00;
		}
	}
}



数据库封装类:

Java代码 复制代码 收藏代码
  1. /*** 
  2.  * 数据库工具类 
  3.  * */  
  4. public class DBTools {  
  5.       
  6.     /**日志对象*/  
  7.     static Logger log =LoggerFactory.getLogger(DBTools.class);  
  8.       
  9.       
  10.     private  static  Connection conn;  
  11.     private  static PreparedStatement ps;  
  12.     private   ResultSet rs;  
  13.     //从虚拟表查询函数  
  14.     private static  String  sql="select datasql.GETGMV(?) as gmv  from dual ";  
  15.     static{  
  16.         try{  
  17.         Class.forName("oracle.jdbc.driver.OracleDriver");  
  18.         conn = DriverManager.getConnection("jdbc:oracle:thin:@ip地址:1521:数据库名""用户名""密码");  
  19.         System.out.println("数据库连接:"+conn);  
  20.         ps=conn.prepareStatement(sql);  
  21.         }catch(Exception e){  
  22.             log.error("初始化oracle驱动异常!", e);  
  23.         }  
  24.     }  
  25.       
  26.     /**根据一个rfxno获取对应的产品的gmv 
  27.      * **/  
  28.     public double getGmvByRfxno(String rfxno){  
  29.         try{  
  30.         ps.setString(1, rfxno);  
  31.         rs = ps.executeQuery();  
  32.         if(rs.next()){  
  33.             double gmv=rs.getDouble("gmv");  
  34. //          System.out.println("gmv是:  "+gmv);  
  35.             return gmv;  
  36.         }  
  37.         rs.close();  
  38.         }catch(Exception e){  
  39.             log.error("根据rfxno获取gmv出错!",e);  
  40.         }  
  41.         return 0.0;  
  42.     }  
  43.     }  
/***
 * 数据库工具类
 * */
public class DBTools {
	
	/**日志对象*/
	static Logger log =LoggerFactory.getLogger(DBTools.class);
	
	
	private  static  Connection conn;
	private  static PreparedStatement ps;
	private   ResultSet rs;
	//从虚拟表查询函数
	private static  String  sql="select datasql.GETGMV(?) as gmv  from dual ";
	static{
		try{
		Class.forName("oracle.jdbc.driver.OracleDriver");
		conn = DriverManager.getConnection("jdbc:oracle:thin:@ip地址:1521:数据库名", "用户名", "密码");
		System.out.println("数据库连接:"+conn);
		ps=conn.prepareStatement(sql);
		}catch(Exception e){
			log.error("初始化oracle驱动异常!", e);
		}
	}
	
	/**根据一个rfxno获取对应的产品的gmv
	 * **/
	public double getGmvByRfxno(String rfxno){
		try{
		ps.setString(1, rfxno);
		rs = ps.executeQuery();
		if(rs.next()){
			double gmv=rs.getDouble("gmv");
//			System.out.println("gmv是:  "+gmv);
			return gmv;
		}
		rs.close();
		}catch(Exception e){
			log.error("根据rfxno获取gmv出错!",e);
		}
		return 0.0;
	}
	}




其实,代码还是比较简单的,在这里,你可以从任何数据源获取需要的数据,而不仅仅是数据库,你也可以从redis,memcache,文件,xml,等等里获取需要组合用的数据。

遇到一个异常:在sql语句后面,不用加分号,类似下面的这样的语句,通过jdbc编译然后调用oracle是不通过的:

Sql代码 复制代码 收藏代码
  1. select datasql.GETGMV(?) as gmv  from dual;  
select datasql.GETGMV(?) as gmv  from dual;


这一点需要注意下。

最后来看下如下在pig脚本里,使用自定义的函数:
(1)使用ant打包自定义的udf函数的jar
(2)在pig脚本里,注册相关的jar包,注意如果有依赖关系,依赖的jar包,也需要注册,例如本例中的oracle的jdbc的驱动包
(3)在对应的地方,通过类的全路径名,引用此函数,完成对应的查询转换,并将新得到的一个字段,作为原始一行记录的字段扩充。

脚本如下:

Java代码 复制代码 收藏代码
  1. --注册依赖的jar包  
  2. register /home/search/dongliang/nsconvent/checklist/ojdbc.jar  
  3. register /home/search/dongliang/nsconvent/checklist/tools.jar  
  4.   
  5.   
  6. --加载原有数据  
  7. m = load '/tmp/mdm/VW_TD_RFX' using PigStorage('\\x07');  
  8. --加载原有数据  
  9. n = load '/tmp/mdm/TD_RFX_PRODUCT' using PigStorage('\\x07');  
  10.   
  11. --过滤出符合时间的数据  
  12.   
  13. m= filter m by ToMilliSeconds(ToDate($3,'yyyy-MM-dd HH:mm:ss')) >= ToMilliSeconds(ToDate('$day 00:00:00','yyyy-MM-dd HH:mm:ss')) and ToMilliSeconds(ToDate($3  
  14. ,'yyyy-MM-dd HH:mm:ss')) <= ToMilliSeconds(ToDate('$day 23:59:59','yyyy-MM-dd HH:mm:ss'))  ;  
  15.   
  16. --提取相关字段,并完成计算  
  17. m = foreach m generate $0 as arfid, $1 as rfxno , com.pig.dhgate.getgvmbyrfxno.GetGmvByRfxno((chararray)$1) as gmv  , $4 as bid ;  
  18. --获取topN数据  
  19. m = limit m 10 ;  
  20. --打印输出  
  21. dump m;  
分享到:
评论

相关推荐

    基于REST接口的PIG的oink.zip

    Oink 是基于 Servlet 的 Pig ,提供以下功能:注册/注销/查看 Pig 脚本注册/注销/查看 jar 文件 (用于自定义 UDF 函数)执行 Pig 工作查看 Pig 工作的数据/状态取消一个 Pig 工作 标签:oink

    Pig编程指南

    《Pig编程指南》不仅为初学者讲解ApachePig的基础知识,同时也向有一定使用经验的高级用户介绍更加综合全面的Pig重要特性,如PigLatin脚本语言、控制台shell交互命令以及用于对Pig进行拓展的用户自定义函数(UDF)等。...

    pig-demo-project:该项目的目的是展示一种设置基于 Apache Pig 的项目的可能方法

    如何编写自定义 Pig UDF 单元测试 UDF。 加载到猪脚本中。 如何编写一个猪脚本 使用外部编写的 Loader ( ) 尝试通过以下方式保持猪脚本尽可能干净 使用属性文件。 只加载它真正需要的 JAR 文件。 将您的 Pig ...

    intellij-pig:Pig 插件为 IntelliJ 添加了 Apache Pig 语言支持

    特征查找 UDF 和 Pig 变量的用法和重构支持数据类型自动完成关键字突出显示代码注释/取消注释大括号匹配语法和错误突出显示自定义颜色设置页面安装从 IntelliJ 插件仓库安装。作者布兰登·卡比拉塞尔·梅利克如何...

    Hadoop权威指南(中文版)2015上传.rar

    用户自定义函数 过滤UDF 计算UDF 加载UDF 数据处理操作 加载和存储数据 过滤数据 分组与连接数据 对数据进行排序 组合和分割数据 Pig实战 并行处理 参数代换 第12章 Hive 1.1 安装Hive 1.1.1 Hive外壳环境 1.2 示例 ...

    Hadoop权威指南 第二版(中文版)

     用户自定义函数  过滤UDF  计算UDF  加载UDF  数据处理操作  加载和存储数据  过滤数据  分组与连接数据  对数据进行排序  组合和分割数据  Pig实战  并行处理  参数代换 第12章 Hive  1.1 安装Hive ...

    Hadoop硬实战 [(美)霍姆斯著][电子工业出版社][2015.01]_PDF电子书下载 带书签目录 高清完整版.rar )

    3.4 自定义文件格式 3.4.1 输入输出格式 技术点18 输入和输出格式为CSV 的文件 3.4.2 output committing 的重要性 3.5 本章小结 第3 部分 大数据模式 4 处理大数据的MapReduce 模式 4.1 Join ...

    Hadoop实战(第2版)

    10.2.1 序列化和反序列化技术点64 载入日志文件10.2.2 UDF、分区、分桶和压缩技术点65 编写UDF 和压缩分区表10.2.3 数据合并技术点66 优化Hive 合并10.2.4 分组、排序和explain 10.3 本章小结11 ...

Global site tag (gtag.js) - Google Analytics