如何找到路径流并使用猪或蜂巢对它们进行排名?

Posted

技术标签:

【中文标题】如何找到路径流并使用猪或蜂巢对它们进行排名?【英文标题】:how to find the pathing flow and rank them using pig or hive? 【发布时间】:2015-09-20 15:39:17 【问题描述】:

以下是我的用例示例。

【问题讨论】:

好的.. 我得到了要求.. 尝试了一段时间来获得实际输出.. 看起来我们需要一个 java UDF 来删除相邻的相同屏幕名称.. 让我再考虑一些时间对此。我想给出一个没有UDF的解决方案 @explorethis :是否可以以纯文本格式添加输入和预期输出?我喜欢尝试这个用例。 @MuraliRao :我无法以相同的顺序格式化。它作为纯文本放置。如果您可以分享您的电子邮件,我将为此发送一个 word 文档 :) @Surender Raja - 你能给我关于以下场景的建议吗***.com/questions/32768964/… 【参考方案1】:

您可以参考this question OP 询问类似问题的地方。如果我正确理解了您的问题,您希望从路径中删除重复项,但前提是它们彼此相邻。所以1 -> 1 -> 2 -> 1 会变成1 -> 2 -> 1。如果这是正确的,那么您不能只对和distinct 进行分组(我相信您已经注意到了),因为它会删除 all 重复项。一个简单的解决方案是编写一个 UDF 来删除这些重复项,同时保留用户的不同路径。

UDF

package something;

import java.util.ArrayList;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public class RemoveSequentialDuplicatesUDF extends UDF 
    public ArrayList<Text> evaluate(ArrayList<Text> arr) 
        ArrayList<Text> newList = new ArrayList<Text>();
        newList.add(arr.get(0));
        for (int i = 1; i < arr.size(); i++) 

            String front = arr.get(i).toString();
            String back  = arr.get(i-1).toString();

            if (!back.equals(front)) 
                newList.add(arr.get(i));
            
        
        return newList;
    

要构建这个 jar,您需要 hive-core.jarhadoop-core.jar,您可以在 Maven Repository 中找到这些。确保您获得在您的环境中使用的 Hive 和 Hadoop 版本。此外,如果您打算在生产环境中运行它,我建议您在 UDF 中添加一些异常处理。 jar 构建完成后,将其导入并运行以下查询:

查询

add jar /path/to/jars/brickhouse-0.7.1.jar;
add jar /path/to/jars/hive_common-SNAPSHOT.jar;
create temporary function collect as "brickhouse.udf.collect.CollectUDAF";
create temporary function remove_dups as "something.RemoveSequentialDuplicatesUDF";

select screen_flow, count
  , dense_rank() over (order by count desc) rank
from (
  select screen_flow
    , count(*) count
  from (
    select session_id
      , concat_ws("->", remove_dups(screen_array)) screen_flow
    from (
      select session_id
        , collect(screen_name) screen_array
      from (
        select *
        from database.table
        order by screen_launch_time ) a
      group by session_id ) b
    ) c
  group by screen_flow ) d

输出

s1->s2->s3      2       1
s1->s2          1       2
s1->s2->s3->s1  1       2

希望这会有所帮助。

【讨论】:

太好了!!我会试试这个,并会让你知道:) 根据我所看到的,我理解你的方法,希望能解决我的问题。 太棒了!它很完美。欣赏 GoBrewer 我需要您的专业知识来解决***.com/questions/32768964/…中发布的问题 对我在***.com/questions/32768964/…的新帖子的任何想法 你能用 pig 重写上面的 hive 逻辑吗?【参考方案2】:

输入

990004916946605-1404157897784,S1,1404157898275
990004916946605-1404157897784,S1,1404157898286
990004916946605-1404157897784,S2,1404157898337
990004947764274-1435162269418,S1,1435162274044
990004947764274-1435162269418,S2,1435162274057
990004947764274-1435162269418,S3,1435162274081
990004947764274-1435162287965,S2,1435162690002
990004947764274-1435162287965,S1,1435162690001
990004947764274-1435162287965,S3,1435162690003
990004947764274-1435162287965,S1,1435162690004
990004947764274-1435162212345,S1,1435168768574
990004947764274-1435162212345,S2,1435168768585
990004947764274-1435162212345,S3,1435168768593


register /home/cloudera/jar/ScreenFilter.jar;

screen_records =  LOAD '/user/cloudera/inputfiles/screen.txt' USING PigStorage(',') AS(session_id:chararray,screen_name:chararray,launch_time:long);

screen_rec_order =  ORDER screen_records  by launch_time ASC;

session_grped = GROUP screen_rec_order BY session_id;

eached = FOREACH session_grped
                      
                         ordered = ORDER screen_rec_order by launch_time;

                        GENERATE group as session_id, REPLACE(BagToString(ordered.screen_name),'_','-->') as screen_str;

                      ;

screen_each  =  FOREACH eached GENERATE session_id, GetOrderedScreen(screen_str) as screen_pattern;

screen_grp   = GROUP screen_each by screen_pattern;

screen_final_each = FOREACH screen_grp GENERATE group as screen_pattern, COUNT(screen_each) as pattern_cnt;

ranker = RANK screen_final_each BY pattern_cnt DESC DENSE;

output_data = FOREACH ranker GENERATE screen_pattern, pattern_cnt, $0 as rank_value;

dump output_data;

我无法找到使用 Pig Builtin 函数删除相同 session_id 的相邻屏幕的方法,因此我使用 JAVA UDF 来删除相邻的屏幕名称。

我创建了一个名为 GetOrderedScreen 的 JAVA UDF 并将该 UDF 转换为 jar 并将该 jar 命名为 ScreenFilter.jar 并在此 Pig 脚本中注册该 jar

下面是 GetOrderedScreen Java UDF 的代码

public class GetOrderedScreen extends EvalFunc<String> 


@Override
public String exec(Tuple input) throws IOException 


    String incoming_screen_str= (String)input.get(0);
    String outgoing_screen_str ="";
    String screen_array[] =incoming_screen_str.split("-->");

    String full_screen=screen_array[0];

  for (int i=0; i<screen_array.length;i++)
  
     String prefix_screen=  screen_array[i];
     String suffix_screen="";
     int j=i+1;

     if(j< screen_array.length)
     
         suffix_screen  = screen_array[j];
     


 if (!prefix_screen.equalsIgnoreCase(suffix_screen))
     
     full_screen = full_screen+ "-->" +suffix_screen;
     

  
  outgoing_screen_str =full_screen.substring(0, full_screen.lastIndexOf("-->")); 


  return outgoing_screen_str;


输出

(S1-->S2-->S3,2,1)
(S1-->S2,1,2)
(S1-->S2-->S3-->S1,1,2)

希望对你有帮助!..也请稍等片刻,看到这个问题的一些好人会有效回答(没有JAVA UDF)

【讨论】:

太棒了!!让我试试看。 一个小问题..类似于等级,我也需要等级..如何从上面的输出中找到等级?例如(S1-->S2-->S3是2级)(S1-->S2是1级)(S1-->S2-->S3-->S1是3级)..基本算箭头数(-->) .. 你能帮忙吗? 我写了一个python脚本来统计子串来达到结果。感谢您的帮助! 我现在尝试在上面的猪脚本中添加两个新列 application_name 和 date,但这样做会遇到麻烦。你能帮忙吗? 您的应用程序名称和日期是什么。您希望所有输出记录保持相同

以上是关于如何找到路径流并使用猪或蜂巢对它们进行排名?的主要内容,如果未能解决你的问题,请参考以下文章

如何对蜂巢中的每一组进行采样?

蜂巢多次计数相同的字段

在哪里进行连接以展平表..?蜂巢或甲骨文

在 Swift 中像在 Java 中一样使用套接字

Bloc如何收听流并发出状态

我想使用某些条件进行排名