Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mongodb PyMongo通过游标使用计算字段更新数组记录_Mongodb_Numpy_Pymongo - Fatal编程技术网

Mongodb PyMongo通过游标使用计算字段更新数组记录

Mongodb PyMongo通过游标使用计算字段更新数组记录,mongodb,numpy,pymongo,Mongodb,Numpy,Pymongo,对于非常大的数据集,精细聚合管道的收集输出基本上类似于以下内容: { "_id" : { "clienta" : NumberLong(460011766), "clientb" : NumberLong(2886729962) }, "states" : [ [ "fixed", "fixed.rotated","fixed.rotated.off" ] ],

对于非常大的数据集,精细聚合管道的收集输出基本上类似于以下内容:

{
    "_id" : {
        "clienta" : NumberLong(460011766),
        "clientb" : NumberLong(2886729962)
    },
    "states" : [ 
        [ 
            "fixed", "fixed.rotated","fixed.rotated.off"

        ]
    ],
    "VBPP" : [ 
        244, 
        182,
        184,
        11,
        299,

    ],
    "PPF" : 72.4,   
}
在转换为数组之前,通过PyMongo直观地(尽管速度较慢)将这些字段更新为其以前的自我(数组的长度和方差)的计算,如下所示:

records_list = []

cursor = db.clientAgg.find({}, {'_id' : 0,
                                      'states' : 1, 
                                      'VBPP' : 1, 
                                      'PPF': 1})
for record in cursor:
    records_list.append(record)

for dicts in records_list:
        dicts['states'] = len(dicts['states'])
        dicts['VBPP']  = np.var(dicts['VBPP'])
我已经编写了各种形式的基本流程来优化速度,但是在将它们转换为数组以通过机器学习估计器之前,在内存中引入500k字典来修改它们是非常昂贵的。我尝试了各种方法,通过光标直接更新记录,但没有成功:

cursor = db.clientAgg.find().skip(0).limit(50000)

def iter():
    for item in cursor:
        yield item

l = []
for x in iter():
    x['VBPP']  = np.var(x['VBPP']) 
    # Or    
    # db.clientAgg.update({'_id':x['_id']},{'$set':{'x.VBPS': somefunction as above }},upsert=False, multi=True)
我还尝试使用Mongo的常用运算符,但没有成功,因为方差非常简单,只需从数组的每个元素中减去平均值,将结果平方,然后对结果求平均值

如果我可以直接成功地修改集合,那么我就可以利用Monary或IOPro等非常快速的工具直接从Mongo将数据加载到numpy数组中,而不需要额外的开销


感谢您抽出时间

MongoDB无法使用从文档字段计算的值更新文档;当前,您只能使用update将值设置为从应用程序传入的常量。因此,您可以将
document.x
设置为2,但不能将
document.x
设置为
document.y+document.z
或任何其他计算值

有关未来可能的功能,请参阅和

在不久的将来,PyMongo将发布一个新版本,允许您在一次网络往返中发送一批不同的更新操作,这将提高您的性能

附录:

我还有两个想法。首先,运行一些Javascript服务器端。例如,要将所有文档的
b
字段设置为
2*a

db.eval(function() {
    var collection = db.test_collection;
    collection.find().forEach(function(doc) {
        var b = 2 * doc.a;
        collection.update({_id: doc._id}, {$set: {b: b}});
    });
});
第二个想法是使用,将集合转换为包含计算字段的第二个集合:

db.test_collection.aggregate({
    $project: {
        a: '$a',
        b: {$multiply: [2, '$a']}
    }
}, {
    $out: 'test_collection2'
});
请注意,
$project
必须明确包含所需的所有字段;默认情况下仅包括
\u id

对于我机器上的一百万个文档,前一种方法需要2.5分钟,后一种方法需要9秒。因此,您可以使用聚合框架将数据从源复制到目标,并包含计算字段。然后,如果需要,将原始集合拖放到源名称


关于这一点,我的最后一个想法是,MongoDB 2.5.3及更高版本可以使用游标从聚合管道流式传输大型结果集。Monary没有理由不能使用该功能,所以您可以在那里提交功能请求。这将允许您通过Monary以您想要的形式从集合中获取文档,而无需实际将计算字段存储在MongoDB中。

很有趣,谢谢您提供的信息。我搜遍了吉拉,但错过了那些伟大的发现。看来我必须把这些对象放到内存中,然后进行计算并写回常量。你对Python的可伸缩解决方案有什么建议吗。我无法控制一些$unwind操作符。遗憾的是,《Monary》的作者已经有相当一段时间处于MIA状态了。似乎没有办法从aggregate()倒带光标。find()只是cursor.rewind()。尝试使用聚合将得到“InvalidOperation:无法调用对命令游标的回放”True——为什么需要回放聚合游标?回放并不特殊;这与在循环中重新创建光标完全相同。倒带光标只需再次将查询发送到服务器,然后再次从服务器检索结果。(看。)所以你要么按照伯尼在谷歌群组中的建议去做(只获取一次结果并处理每个字段),要么创建一个新的光标来检索每个字段。