我正在尝试根据this document将预先汇总的效果指标存储在分片的mongodb中。
我正在尝试更新记录中的分钟子文档,这些子文档可能存在也可能不存在这样的upsert(self.collection
是一个pymongo集合实例):
self.collection.update(query, data, upsert=True)
查询:
{ '_id': u'12345CHA-2RU020130304',
'metadata': { 'adaptor_id': 'CHA-2RU',
'array_serial': 12345,
'date': datetime.datetime(2013, 3, 4, 0, 0, tzinfo=<UTC>),
'processor_id': 0}
}
数据:
{ 'minute': { '16': { '45': 1.6693091}}}
问题是,在这种情况下,'minute'子文档始终只有最后hour: { minute: metric}
条目,分钟子文档不会为其他小时创建新条目,它总是覆盖一个条目。
我还尝试使用$ set样式数据条目:
{ '$set': { 'minute': { '16': { '45': 1.6693091}}}}
但最终却是一样的。
我做错了什么?
答案 0 :(得分:2)
在列出的两个示例中,您只需将字段('minute'
)设置为特定值,唯一的原因是它在您第一次更新时添加,因为字段本身不存在,因此必须被创造。
很难准确确定你在这里拍摄的内容,但我认为你可以做的是稍微改变你的模式,以便'minute'
是一个数组。然后,您可以使用$push
添加值,无论它们是否已存在,如果您不想要重复,也可以使用$addToSet
。
我必须稍微修改一下你的文档才能使它在shell中有效,所以我的_id
(以及其他一些字段)与你的文档略有不同,但它仍然应该足够接近于说明:< / p>
db.foo.find({'_id': 'u12345CHA-2RU020130304'}).pretty()
{
"_id" : "u12345CHA-2RU020130304",
"metadata" : {
"adaptor_id" : "CHA-2RU",
"array_serial" : 12345,
"date" : ISODate("2013-03-18T23:28:50.660Z"),
"processor_id" : 0
}
}
现在让我们添加一个minute
字段,其中包含一系列文档而不是单个文档:
db.foo.update({'_id': 'u12345CHA-2RU020130304'}, { $addToSet : {'minute': { '16': {'45': 1.6693091}}}})
db.foo.find({'_id': 'u12345CHA-2RU020130304'}).pretty()
{
"_id" : "u12345CHA-2RU020130304",
"metadata" : {
"adaptor_id" : "CHA-2RU",
"array_serial" : 12345,
"date" : ISODate("2013-03-18T23:28:50.660Z"),
"processor_id" : 0
},
"minute" : [
{
"16" : {
"45" : 1.6693091
}
}
]
}
然后,为了说明添加,添加一个稍微不同的条目(因为我使用$addToSet
这是添加新字段所必需的:
db.foo.update({'_id': 'u12345CHA-2RU020130304'}, { $addToSet : {'minute': { '17': {'48': 1.6693391}}}})
db.foo.find({'_id': 'u12345CHA-2RU020130304'}).pretty()
{
"_id" : "u12345CHA-2RU020130304",
"metadata" : {
"adaptor_id" : "CHA-2RU",
"array_serial" : 12345,
"date" : ISODate("2013-03-18T23:28:50.660Z"),
"processor_id" : 0
},
"minute" : [
{
"16" : {
"45" : 1.6693091
}
},
{
"17" : {
"48" : 1.6693391
}
}
]
}
答案 1 :(得分:2)
我最终设置了这样的字段:
查询:
{ '_id': u'12345CHA-2RU020130304',
'metadata': { 'adaptor_id': 'CHA-2RU',
'array_serial': 12345,
'date': datetime.datetime(2013, 3, 4, 0, 0, tzinfo=<UTC>),
'processor_id': 0}
}
我正在设置这样的指标:
data = {"$set": {}}
for metric in csv:
date_utc = metric['date'].astimezone(pytz.utc)
data["$set"]["minute.%d.%d" % (date_utc.hour,
date_utc.minute)] = float(metric['metric'])
创建如下数据:
{"$set": {'minute.16.45': 1.6693091,
'minute.16.46': 1.566343,
'minute.16.47': 1.22322}}
因此,当self.collection.update(query, data, upsert=True)
运行时,它会更新这些字段。