`
weitao1026
  • 浏览: 1050257 次
  • 性别: 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;  
分享到:
评论

相关推荐

    pig udf 函数(urldecode row_number tomap)

    在 Pig Latin 中,你可以定义一个自定义 UDF 来实现这个功能,如下所示: ```java public class URLDecode extends EvalFunc&lt;String&gt; { @Override public String exec(Tuple input) throws IOException { if ...

    pig-udf:猪用UDF样本

    在这个名为“pig-udf:猪用UDF样本”的项目中,我们主要关注的是如何使用Java来编写和集成自定义的UDF到Pig的处理流程中。 一、Pig UDF简介 UDF是Pig处理复杂数据转换和计算的关键组成部分。通过UDF,用户可以编写...

    pig编程指南中的样例脚本、UDF、数据集

    Pig Latin本身提供的函数可能无法满足所有需求,这时就可以编写自定义的Java函数并集成到Pig作业中。UDF可以用于执行数据清洗、计算、字符串操作等任务,极大地丰富了Pig的数据处理能力。编写UDF时,需要继承Pig的...

    pdi-pig-udfs:使用 Pentaho 数据集成的 Pig UDF 的集合

    3. **内置与自定义 UDF**:Pig 内置了一些基本的 UDF,如 `LOAD` 和 `STORE`,而自定义 UDF 可以实现特定的数据处理需求。 4. **Pig UDF 类型**:包括 EvalFunc(用于数据转换)、FilterFunc(用于过滤数据)和 Load...

    pig-0.7.0.tar.gz

    3. **UDF(用户定义函数)扩展**:0.7.0版本提供了更多的内置UDF,同时也支持用户自定义UDF,这极大地增强了Pig的功能性和灵活性。用户可以通过编写Java代码或使用其他语言(如Python或JavaScript)来扩展Pig的功能...

    udf.zip_UDF案例_udf_udf模板

    UDF,全称为User Defined Function(用户自定义函数),在编程和数据分析领域中扮演着重要角色,尤其是在数据库管理系统、大数据处理框架如Hadoop的Hive、Pig或Spark SQL等中。UDF允许用户扩展系统功能,以满足特定...

    pig源码0.15版

    Pig支持用户自定义函数,以扩展其功能。源码中,UDF的注册、调用及执行流程清晰可见。这包括了对Java和Python UDF的支持,以及如何将UDF集成到Pig Latin语句中进行数据转换和处理。 3. **数据类型和Schema**: 在...

    基于REST接口的PIG的oink.zip

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

    Pig编程指南

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

    pig的源码包

    同时,Pig还支持自定义函数(UDF),源码包中的FuncSpec和GenericUDF接口展示了如何扩展Pig的功能。 5. 执行模型:Pig的执行模型基于Hadoop,它将Pig Latin脚本转化为一系列的MapReduce作业。源码中,Executor和...

    pig java 编程jar包

    通过Java API,开发者可以直接与Pig交互,创建自定义函数(UDF)来扩展Pig的功能,满足特定的数据处理需求。 2. **pigunit.jar**: `pigunit.jar`是Pig的单元测试框架,它允许开发人员对Pig Latin脚本进行自动化...

    pig官方基础教程

    此外,教程还会介绍用户自定义函数(UDF)。UDF允许用户扩展Pig的功能,通过编写自己的函数来处理数据。Pig支持多种语言编写UDF,包括Java、Python、JavaScript等。 Pig的基础教程会以理论讲解配合实际案例的方式,...

    pig学习笔记

    2. **灵活性** :Pig 支持自定义函数(UDF),允许用户添加自己的业务逻辑,大大增强了其处理复杂数据类型的能力。 3. **性能优化** :Pig 在运行时会自动优化数据处理流程,避免不必要的计算,提高整体效率。 4. **...

    Apache Hadoop---Pig.docx

    3. 易于控制执行:可以自定义执行流程,如插入 UDF,以便进行特定的数据处理。 4. 延迟执行:Pig 采用延迟评估策略,只有在实际需要输出时才执行操作,有利于优化执行计划。 5. 有效利用 Hadoop 功能:Pig 可以充分...

    Programming Pig(pig编程).pdf

    此外,Pig还支持用户自定义函数(UDF),这使得Pig可以扩展使用Java、Python、JavaScript等其他语言编写的函数,从而执行更复杂的数据处理任务。这为Pig提供了极大的灵活性和强大的处理能力。 最后,由于Pig与...

    pig-0.12.1.tar.gz

    此外,由于Pig支持用户自定义函数(UDF),用户还可以编写Java代码来扩展其功能,以满足特定的业务需求。 总的来说,"pig-0.12.1.tar.gz"是一个强大的工具,为Linux上的Hadoop用户提供了一种高效、灵活的数据处理...

    pig-0.12.0-cdh5.5.0.tar.gz

    这些 UDF 可以用于处理特定的数据类型、执行复杂的计算或集成自定义的算法。 6. **调试和日志**:Pig 提供了详细的执行计划和日志,便于开发者理解任务执行的过程和可能出现的问题。这对于调试和优化 Pig 脚本非常...

Global site tag (gtag.js) - Google Analytics