最新 分享

Publish our news and thoughts with all.

Popular Articles

Recent Stories

数据驱动的产品优化

如今,随着大数据和精益数据分析的普及流行,不会看数据的产品经理也不能称作合格的产品经理了。为了能够使我们的产品设计更加智能,避免拍脑袋/因果驱动的产品设计,产品经理在产品设计阶段就要考虑结合自己产品的业务目标来定义对应的数据统计指标,在产品灰度或者上线时跟踪产品运营数据的变动,分析趋势,发现问题。然而,现在的很多公司在产品设计和运营方面常常存在如下问题:1)效率低,错过了利用数据决策的最好机会。数据工程师由于面对来自产品、运营甚至boss的数据需求,并且有些数据准备得不充分,数据来源并不好,需要重新获取数据,导致整个跑数据的流程非常耗时。2)数据分析的指标需要更加细化。例如用户流失,仅看宏观的仪表盘数据是远远不够的,要按地域、渠道等不同方式切分进行追查,看是整体量下滑还是某一个渠道出现问题造成的用户流失。 如何去研究数据,用好数据,来更好地帮助我们进行产品设计和产品迭代优化?我觉得应该从产品数据分析的目的谈起。

读懂活跃数据

用户运营核心的方法论就三个:拉新,促活和留存。拉新可以作为渠道推广单独讨论,而促活和留存则相辅相成。非运营岗,或者其他类型的运营,通常只会注重一个活跃数据的果,而不会注意活跃数据的因。我们在这里就抽丝剥茧,教大家比较快速地了解活跃体系。互联网公司对活跃用户的定义大同小异,主要以用户打开APP一次记为一个活跃用户。按此基础可以在时间维度引申出周活跃用户,月活跃用户。即在一个自然周内打开一次APP,则本周为周活跃用户。月活跃用户同理。我们假设有一款新产品,这是它四个月内的活跃数据。嗯,看来不错。

Hive常见操作命令

1. hive模糊搜索表show tables like '*name*';2. 查看表结构信息desc formatted tablename;desc table_name;3. 查看分区信息show partitions tablename;4. 根据分区查询数据select table_coulm from tablename where partitionname = '2016-02-25';5. 删除分区alter table test drop partition(dt='2016-03-01');alter table  test drop partition(dt='2016-01-17');6. 杀死某个任务  不在hive shell中执行Hadoop job -kill job_201403041453_583157. hive命令行操作执行一个查询,在终端上显示mapreduce的进度,执行完毕后,最后把查询结果输出到终端上,接着hive进程退出,不会进入交互模式。hive -e 'select table_cloum from table'-S,终端上的输出不会有mapreduce的进度,执行完毕,只会把查询结果输出到终端上。这个静音模式很实用,,通过第三方程序调用,第三方程序通过hive的标准输出获取结果集。hive -S -e 'select tablecloum from table'执行sql文件hive -f hive_sql.sql8. 查看文件大小及删除文件Hive>dfs –du /xx/xxHive>dfs –rmr /xx/xx9. mapjoin的使用 应用场景:1.关联操作中有一张表非常小 2. 不等值的链接操作select /*+ mapjoin(A)*/ f.a,f.b from A t join B f  on ( f.a=t.a and f.ftime=20110802);10. hive开启简单模式不启用mrset hive.fetch.task.conversion=more;11. hive修改表名ALTER TABLE oldtablename RENAME TO newtablename;12. hive添加字段alter table temp add columns(current_session_timelenth_count bigint comment '页面停留总时长');ALTER temp CHANGE current_session_timelenth current_session_timelenth bigint comment '当前会话停留时间';------------------------------------------------------------------------------------------Hive支持大量SQL数据定义语言(Data Manipulation Language,DML)中的现有功能,包括以下各种语句:使用where条件过滤表的行使用列或子查询的select表达式使用等值连接,连接多张表合并表的所有行或子查询针对多个“分组”的列进行聚合计算将查询结果存入另一张表导出表中的内容到本地目录或HDFS目录中以下参考自点击打开链接1. 只查询前两条:select  * from  student  limit  2 ;2. 统计一个表的行数:select  count(*)  from student ;3. 求一个表id字段的id 之和:select  sum(id)  from  student ;4. 查询分区表select  *  from  beauties  where  nation='China' ;5. 多表关联:select  t . account ,  u . name , t . income , t . expenses , t . surplus from  user_info  u  join  (select  account ,  sum(income)  as  income ,  sum(expenses) as  expenses , sum(income-expenses)  as  surplus  fromtrade_detail  group  by  account)  t  on  u . account  =  t . account ;别名select count(distinct e.uid) from (select * from tablenamewhererank <=3 and order =1) e;小括号中返回的也是一个表,它只是临时的 别名为e查搜索过"奥巴马" 的用户所搜过的关键字select  m.uid,m.keyword  from (select  distinct n.uid fromtablenamewhere keyword like '%奥巴马%' n ) mwhere m.uid=n.uid;查搜索过"奥巴马" 的用户所搜过的不包含"奥巴马"本身的关键字select m.uid,m.keyword from sogou_20111230 m join (select distinct uid from sogou_20111230 where keyword like '%奥巴马%') n on m.uid=n.uid where m.keyword not like '%奥巴马%';UNION ALL可以将2个或多个表进行合并select count(distinct e.uid)from(select * from tablename where rank<11union allselect * from ext_sogou_20111230_limit3 where rank < 11) e;6. 去重查询:group by的使用select  *  from  mytable  group  by  uid ;Group by 语句通常会和聚合函数一起使用,按照一个或者多个对结果进行分组,然后对每个组执行聚合操作select year(ts), avg(rank) from tablename where ts like '%2011' group by year(ts);7. 独立UID总数:select  count(distinct(uid)) from  mytable ; (高效) 或者    select  count(*) from(select  *  from mytable  group  by  uid)  a ;8. 查询频度排名(频度最高的前50):select keyword,count(*) as cnt from test group by keyword order by cnt desc limit 50;9. 添加防止删除的保护:alter table tablename> partition (day='0925') enable no_drop;删除添加的"删除"保护:alter table tablename> partition (day='20161207') disable no_drop;10. 添加防止查询的保护:alter table tablename> partition (day=20161207') enable offline;删除防止查询的保护:alter table tablename> partition (day='20161207') disable offline;11. 强转:select cast(rank as DOUBLE) from tablename limit 10;12. 拼接:select concat(uid,url) from tablename limit 10;13. 查找url字符串中的5位置之后字符串str第一次出现的位置select locate("str",url,5) from tablename limit 100;14. 抽取字符串str中符合正则表达式url的第5个部分的子字符串select regexp_extract("str",url,5) from tablename limit 100;15.   按照正则表达式"0"分割字符串uid,并将分割后的部分以字符串数组的方式返回select split(uid,"0") from tablename limit 100;16.   对字符串url,从0处开截取长度为3的字符串,作为其子字符串select substr(url,0,3) from tablename limit 3;17. 将字符串url中所有的字母转换成大写字母select upper(url) from tablename limit 3;18. where  ..and  或者 where ....or   where的 两种条件查询select * from  tablename where rank<=3 and order =1 limit 3;select * from  tablenamewhere rank !=0 or order =1 limit 3;19. like 过滤字符串select *  from  tablename where url like '%http%' limit 10;rlike 通过Java的正则表达式过滤  *与%功能一样 ,它是hive中扩展功能的操作符select * from tablenamewhere url rlike  ' .*http.* ' limit 3;20. left semi-join 左半表 semi 半挂的 半独立的select * from be where rank in(1,2,5);select  * from  tablenamem left semi join  ext_sogou_20111230_limit3  n on m.rank=n.rank;21. 视图 hive只支持逻辑视图 作用降低查询复杂度创建视图create view sogou_view  asselect * from tablenamewhere rank <=3;22. 索引Hive的索引需要单独创建表实现创建索引CREATE INDEX employees_index ON TABLE employees (name) AS'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'WITH DEFERRED REBUILD IDXPROPERTIES('creator' = 'me','created_at '='some  time') IN TABLE employees_index_table;23. 上午7-9点之间,搜索过“百度”的用户,哪些用户直接点击了百度的URL老师:select distinct n.uid from (select * from sogou_view where keyword ='百度')and  substr(ts,9,2) in ('07','08','09')) n where n.url like '%baidu.com%';select uid  from sogou_view where (cast(substr(ts,9,2)as int)>7  or cast(substr(ts,9,2) as int)<9) and urllike '%www.ganji.com%' or keyword like '%百度%' ;select uid  from sogou_view where substr(ts,9,2) in ('07','08','09') and urllike '%www.ganji.com%' and  keyword like '%百度%' ;24. 保存Hive查询结果到本地这个方法最为常见,sql的查询结果将直接保存到/tmp/out.txt中$ hive -e "select user, login_timestamp from user_login" > /Downloads/result.txt

ubuntu 16.04升级php7.0至7.2

直接命令升级1. apt-get update && apt-get upgrade2. apt-get install software-properties-common3. add-apt-repository ppa:ondrej/php4. apt-get update5. apt-get upgrade php升级后安装对应的扩展apt-get install php7.2-mbstringapt-get install php7.2-gdapt-get install php7.2-mysqlapt-get install php7.2-curl查看已安装的php包dpkg -l | grep php删除旧版本sudo apt-get purge php7.0 php7.0-common# 查看php版本php -v

微信小程序内嵌web-view并实现小程序支付的几个坑

最近实现了微信小程序web-view内嵌Joomla商城并实现小程序支付。记录一下几个坑(折腾了很久才搞通)#code的获取一开始在小程序端使用wx.login获取到code并通过get方法传递给webview里面的接口页面,想要返回openid给小程序并记录,但是发现等到支付环节的时候,无法再次取得openid,于是在这个地方卡了很久,最后的解决方案是:

  1. 在着陆页立即使用cookie记录code,防止页面跳转后code丢失
  2. 在支付环节才调用方法获取openid,在小程序端先不存储openid,因为小程序端只是完成支付动作,而且通过同一个code只能调用一次接口获取openid
(待更新)

微信小程序开发|获取openid

  • 我们在使用小程序wx.login API进行登录的时候,直接使用wx.getUserInfo是不能获取更多的信息的,如微信用户的openid。 
    官方提示,需要发送获取到的code进行请求到微信的后端API,进行用户解密之类的操作才可以获取,
根据文档,只需要进行一个get请求到如下地址即可:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_codeappid和secret在微信小程序后台可以看到,js_code为使用wx.login登录时获取到的code参数数据,grant_type这个不用改动。

  • js文件
 var openId = (wx.getStorageSync('openId'))        if (openId) {          wx.getUserInfo({            success: function (res) {              that.setData({                nickName: res.userInfo.nickName,                avatarUrl: res.userInfo.avatarUrl,              })            },            fail: function () {              // fail              console.log("获取失败!")            },            complete: function () {              // complete              console.log("获取用户信息完成!")            }          })        } else {          wx.login({            success: function (res) {              console.log(res.code)              if (res.code) {                wx.getUserInfo({                  withCredentials: true,                  success: function (res_user) {                    wx.request({                     //后台接口地址                      url: 'https://....com/getopenid',                      data: {                        code: res.code,                        encryptedData: res_user.encryptedData,                        iv: res_user.iv                      },                      method: 'GET',                      header: {                        'content-type': 'application/json'                      },                      success: function (res) {                        // this.globalData.userInfo = JSON.parse(res.data);                        that.setData({                          nickName: res.data.nickName,                          avatarUrl: res.data.avatarUrl,                        })                        wx.setStorageSync('openId', res.data.openId);                      }                    })                  }, fail: function () {                    wx.showModal({                      title: '警告通知',                      content: '您点击了拒绝授权,将无法正常显示个人信息,点击确定重新获取授权。',                      success: function (res) {                        if (res.confirm) {                          wx.openSetting({                            success: (res) => {                              if (res.authSetting["scope.userInfo"]) {////如果用户重新同意了授权登录                                wx.login({                                  success: function (res_login) {                                    if (res_login.code) {                                      wx.getUserInfo({                                        withCredentials: true,                                        success: function (res_user) {                                          wx.request({                                           url: 'https://....com/getopenid.php',                                            data: {                                              code: res_login.code,                                              encryptedData: res_user.encryptedData,                                              iv: res_user.iv                                            },                                            method: 'GET',                                            header: {                                              'content-type': 'application/json'                                            },                                            success: function (res) {                                              that.setData({                                                nickName: res.data.nickName,                                                avatarUrl: res.data.avatarUrl,                                              })                                              wx.setStorageSync('openId', res.data.openId);                                            }                                          })                                        }                                      })                                    }                                  }                                });                              }                            }, fail: function (res) {                            }                          })                        }                      }                    })                  }, complete: function (res) {                  }                })              }            }          })        }  },  globalData: {       userInfo: null  }
开始写服务端,也很容易。首先获取从小程序传过来的code再配置自己小程序的appid和appscret把这些参数拼接到api接口上进行请求发送就可以返回openid和session_key
<?php//声明CODE,获取小程序传过来的CODE$code = $_GET["code"];//配置appid$appid = "修改成你小程序的APPID";//配置appscret$secret = "修改成你小程序的APPSECRET";//api接口$api = "https://api.weixin.qq.com/sns/jscode2session?appid={$appid}&secret={$secret}&js_code={$code}&grant_type=authorization_code";//获取GET请求function httpGet($url){    $curl = curl_init();    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);    curl_setopt($curl, CURLOPT_TIMEOUT, 500);    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true);    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, true);    curl_setopt($curl, CURLOPT_URL, $url);    $res = curl_exec($curl);    curl_close($curl);    return $res;}//发送$str = httpGet($api);echo $str;?>
OK完成!把服务端上传到服务器,换到上面的这里https://....com/getopenid.php然后就可以再控制台打印出openid和session_key了获取到了,你想怎么玩就怎么玩!后面可以通过wx.getUserinfo获取用户基本信息(头像,昵称,城市,个性签名等相关信息)