MongoDB记录用户行为

1、MongoDB的复杂查询

首先,需要统计的数据结构如下,可以看到每一篇文章/视频及用户组成了一个文档,然后具体的用户行为,比如阅读/观看、点赞、不喜欢等,存在了UserBehaviorItems这个数组里。现在,需要统计的数据是,每一天视频的播放次数。这里如果是在关系型数据库下,SQL写起来还是挺简单的:根据用户行为的记录时间分组,然后筛出视频的播放行为,进行count()操作即可。但是,因为我们需要分组的据存储在每一个文档的数组中,使用mongo shell处理起来,还是有一些繁琐的。下面就展开说一下,根据子文档中的数据进行分组查询的具体处理。

1.png

2、根据mongo中的子文档数据进行分组查询

首先,我们要将子文档中的数据"展开",拆分成多条数据,每条数据包含数组中的一个值,这里需要用到:$unwind。

例如:

{ "_id" : 1, "item" : "ABC", list: [ "1", "2", "3"] }

执行:db.test.aggregate( [ { $unwind : "$list" } ] )

得到:
{ "_id" : 1, "item" : "ABC", "list" : "1" }
{ "_id" : 1, "item" : "ABC", "list" : "2" }
{ "_id" : 1, "item" : "ABC", "list" : "3" }
复制代码

将数据都展开后,就可以进行分组操作了。这里需要特别说明下,mongo中的管道这个概念。管道表示:由一个或多个处理文档的阶段组成,这里的阶段就是指的$unwind这些操作。上一个管道的处理结果将会交给下一个管道进行处理。然后,在这里又遇到了一个很坑的问题,我们要根据用户行为的记录日期来分组,但是这里的日期是以时间戳的形式记录的。而且这个时间戳是APP端传过来的,ios端传的是10位时间戳,android端传的是13位,这就很蛋疼了。这里我是用了两个管道来处理的,先判断时间戳的位数,如果为10位那么就乘以1000,统一调整成13位后再转换成日期,然后进行分组排序操作。最后,实现命令如下:

db.getCollection('user_behavior').aggregate([
    {
        # 根据行为类型筛选出视频观看记录
        $match: {
            "behavior_object_type": {
                $ne: 1
            },
        }
    },
    {
        $unwind: "$UserBehaviorItems"
    }, 
        {
            #把时间戳统一成13位
            $project : {
                resDate: {
                    $cond: { if: { $gte: [ {$strLenCP : {$toString: "$UserBehaviorItems.start_time"}}, 12 ]  }, then: {$multiply:["$UserBehaviorItems.start_time", 1]}, else: {$multiply:["$UserBehaviorItems.start_time", 1000]} }
                }
            }
        },
    {
        #将13位时间戳格式化位yyyy-MM-dd形式
        $project: {
            convertedDate: {
                $dateToString: {
                    format: "%Y-%m-%d",
                    date: {
                        $toDate: "$resDate"
                    }
                }
            }
        }
    },
    {
        # 根据日期进行分组
        $group: {
            _id: "$convertedDate",
            count: {
                $sum: 1
            }
        }
    },
    {   
        # 倒序展示,这里的_id指的是$convertedDate,所以是根据日期进行倒序排序
        $sort: {
            "_id": - 1
        }
    }
]);
复制代码

执行结果:

2.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值