2014-03-14 49 views
0

我有一个〜500万个文件的表格集合。他们看起来像下面这样:为什么mongo总计花费这么长时间?

fr to weight 

我有frto6000可能值。我创建了以下代码,将所有可能的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是集我有我的约5万份文档。

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?

UPDATE

字段frto包含在1-100000范围内的整数,而weight是小float。我尽量让frto之间的所有可能的组合和值相加这些组合,因为有可能是其中有frto同一数据库中有重复的文件(如fr=1 to=2 weight=0.004fr=1 to=2 weight=0.01,所以在这种情况下,我想有在我entropyfr=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)])

+0

你有'fr'和'to'的索引吗?在您选择的“范围”中匹配多少个文档。 –

+0

是的,我用'db.calls.ensure_index([(“fr”,1),(“to”,1)])'。 “范围”是什么意思? – Pio

+0

通过添加“fr”和“to”条件,可以“匹配”多少个文档。通过描述更多你想要做的事情,你的问题可能会更好地解释。那么你是否想要所有'fr'和'to'的唯一值? –

回答

1

的你正在尝试做的基本形式,并指数在整个事情没有迭代是这样的:

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

现在这可能以及炸毁你,所以你可能需要做一些循环和“范围”值,如下所示:

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为你做好工作,并将其分解为可管理的块,其中结果可能对于一次获取来说太大。

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

+0

谢谢!这很酷 :)。尽管现在我已经手动添加了索引,并且速度比以前更快。但我也会添加您的解决方案。 – Pio

+1

@Pio如果一气呵成是不可能的。那么至少分割范围不仅会比当前代码更快,而且写入也更清晰。 –

+0

@Pio当前聚合将返回所有匹配(分组)项目的数组,这正是您现在正在处理它的方式。唯一的区别是响应中有多个元素。所以你会循环的结果。在shell中试试看看输出格式。 –

相关问题