为什么mongo总和需要这么长时间?

时间:2014-03-14 08:01:55

标签: sql mongodb mongodb-query aggregation-framework pymongo

我有一个约500万份文件的表格集。它们如下所示:

 fr to weight

6000frto个可能的值。我创建了以下代码,将所有可能的fr字段中的所有权重加到to,例如

1 1 sum(all documents with fr=1 to=1)
1 2 sum(all documents with fr=1 to=2)
...

我使用pyMongo来编写脚本,而cells是包含所有可能的fr / to字段的数组,calls是我的集合有我的〜500万份文件。

for _from in cells: #pair up each cell with each other cell
     for _to in cells:
             s = calls.aggregate([
                      {
                              '$match':
                              {
                                      "fr": _from,
                                      "to": _to
                              }
                      },
                      {
                              '$group': {'_id': 'null', 'sum': {'$sum':'$weight'}}
                      }])
              if s['result']:
                     fr_to_sum = s['result'][0]['sum']
                     _id = entropy.insert({
                                     'to': _to,
                                     'fr': _from,
                                     'sum': fr_to_sum
                             })

我正在使用一台机器。

另一个数据库会更好吗?例如。一些SQL?

更新

字段frto包含1-100000范围内的整数,而weight是一个小float。我尝试在frto之间进行所有可能的组合,并对这些组合的值求和,因为数据库中可能存在具有frto的重复文档相同(例如fr=1 to=2 weight=0.004fr=1 to=2 weight=0.01,所以在这种情况下,我希望在我的entropy表格中fr=1 to=2 weight=0.014

就像一个样本

 >> db.week_calls.count({'fr':10, 'to':102})
 >> 4

致电db.week_calls.getIndexes()后我

    {
    "v" : 1,
    "key" : {
        "_id" : 1
    },
    "ns" : "db.week_calls",
    "name" : "_id_"
}

这看起来很奇怪,因为我使用db.calls.ensure_index([("fr",1), ("to",1)])

创建并索引整个事物

1 个答案:

答案 0 :(得分:1)

您要尝试做的基本形式,没有迭代是这样的:

db.collection.aggregate([
    { "$group": {
        "_id": { 
           "fr" : "$fr",
           "to" : "$to",
        },
        "sum": { "$sum": "$weight" }
    }}
])

现在可能会爆炸,因此您可能需要执行一些循环并“range”值,如下所示:

db.collection.aggregate([
    { "$match": {
       "fr": { "$gt": 0, "$lte": 10000 },
       "to": { "$gt": 0, "$lte": 10000 }
    }},
    { "$group": {
           "_id": { 
                "fr" : "$fr",
                "to" : "$to",
           },
           "sum": { "$sum": "$weight" }
   }}
])

分段所有这些文档,然后获取下一个

db.collection.aggregate([
    { "$match": {
       "fr": { "$gt": 10000, "$lte": 20000 },
       "to": { "$gt": 10000, "$lte": 20000 }
    }},
    { "$group": {
             "_id": { 
                  "fr" : "$fr",
                  "to" : "$to"
             },
            "sum": { "$sum": "$weight" }
    }]
])

哪种解决方案最适合您。

一般来说,让$group为您完成工作并将其分解为可管理的块,其结果可能对于一次获取而言太大。

在将来的版本中,aggregate将返回一个游标。