当前位置:脚本大全 > > 正文

pymongo是否线程安全(pymongo中group by的操作方法教程)

时间:2021-11-04 19:33:59类别:脚本大全

pymongo是否线程安全

pymongo中group by的操作方法教程

前言

使用 pymongo 进行 group by 操作有两种基本方式,他们都是 mongodb 的原生命令,于 Collection 对象上调用。

  • ?
  • 1
  • 2
  • def aggregate(self, pipeline, **kwargs):
  • def group(self, key, condition, initial, reduce, finalize=None, **kwargs):
  • 示例数据

    演示用的数据为一个订单表,含有以下字段:

    Order

    _id: ObjectID
    userid: int
    itemid: int
    amount: int
    time:   string

    主要任务为:

    即分别为:单键分组和多键分组

    aggregate

    聚合操作只接受一个列表类型的参数 —— pipeline。其每一个元素都是一步操作(stage)。全部可用的 stage 可参见:

    https://docs.mongodb.com/manual/meta/aggregation-quick-reference/#stages

    注意 pipline 里面的 stage 是有序且可重复的,mongodb 会顺序执行,因此一定要记得把像 $match 这样的 stage 放前面。

    单键分组

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • start_time = '2010-10-10 00:00:00'
  • end_time = '2010-10-10 23:59:59'
  •  
  • match = {
  •  'time': {
  •  '$gte': start_time,
  •  '$lte': end_time,
  •  }
  • }
  •  
  • groupby = 'userid'
  •  
  • group = {
  •  '_id': "$%s" % (groupby if groupby else None),
  •  'count': {'$sum': 1}
  •  
  • }
  •  
  • ret = collection.aggregate(
  •  [
  •  {'$match': match},
  •  {'$group': group},
  •  ]
  • )
  •  
  • >>> ret
  • [{'_id': 123, 'count': 500}, ...]
  • $group 指定了返回数据的格式,其中 _id 字段是分组的键。

    多键分组

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • groupby = ['itemid', 'userid']
  •  
  • group = {
  •  '_id': {key: ('$%s' % key) for key in groupby} or {'None': '$None'},
  •  'count': {'$sum': '$amount'}
  • }
  •  
  • ret = collection.aggregate(
  •  [
  •  {'$match': match},
  •  {'$group': group},
  •  ]
  • )
  •  
  • >>> ret
  • [{'_id': {'itemid': 111, 'user_id': 123}, 'count': 100}, ...]
  •  

    这里与单键分组的区别仅在于 _id 的类型,改成了一个字典,从而允许多键组合。

    为了提高通用性,建议始终使用字典的格式。

    另外,既然字符串和字典都可以做键,那么列表行不行呢?答案是不行,列表里的元素,(如 '$userid') 并不会被自动识别为字段,而是仅作一般字符串处理。

    最后关于 aggregate 中可用的运算操作符,可参见:

    https://docs.mongodb.com/manual/reference/operator/aggregation/#accumulators

    如其中的 $addToSet 也是颇有用处,可以用来实现 “统计每个人都买过哪些 itemid” 这样的功能:

  • ?
  • 1
  • 2
  • 3
  • 4
  • group = {
  •  '_id': {'userid': '$userid'},
  •  'dist_itemids': {'$addToSet': '$itemid'},
  • }
  • group

    相较于 aggregate 的全能,group 是专门处理分组操作的一个命令,因此这个方法的参数也更明确,主要参数为:

    例:

  • ?
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • key = ['userid', 'itemid']
  • condition = {
  •  'time': {
  •  '$gte': start_time,
  •  '$lte': end_time,
  •  }
  • }
  • initial = {'count': 0}
  • reducer = Code("""
  •  function(obj, prev) {
  •  prev.count = prev.count + obj.amount
  •  }
  • """)
  •  
  • ret = collection.group(key, condition, initial, reducer)
  •  
  • >>> ret
  • [{'userid': 110, 'itemid': 123, 'count': 500.0}, ...]
  • 这里的分组数据聚合,是通过 reduce 函数实现的,这个函数与 python 的 reduce 不同,它不需要返回值,而是直接修改 prev 参数即可,这个参数会自动代入下一次调用。这可能是 js 的实现。

    须注意的是 js 默认返回浮点数。

    总结

    以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对开心学习网的支持。

    原文链接:https://my.oschina.net/lionets/blog/727188

    标签:
    上一篇下一篇

    猜您喜欢

    热门推荐