我在MongoDB中存储时间序列,结构如下:
{
"_id" : ObjectId("5128e567df6232180e00fa7d"),
"values" : [563.424, 520.231, 529.658, 540.459, 544.271, 512.641, 579.591, 613.878, 627.708, 636.239, 672.883, 658.895, 646.44, 619.644, 623.543, 600.527, 619.431, 596.184, 604.073, 596.556, 590.898, 559.334, 568.09, 568.563],
"day" : 20110628,
}
values-array表示每小时的值。因此,位置非常重要,因为位置0 = first hour
,1 = second hour
等等。
更新特定小时的值非常简单。例如,要更新当天的第7个小时,我会这样做:
db.timeseries.update({day:20130203},{$set : {values.6 : 482.65}}, {upsert : true})
我的问题是我想使用 upsert ,就像这样
db.timeseries.update({day:20130203},{$set : {values.6 : 482.65}})
但是如果文档不存在,MongoDB将会嵌入嵌入式数组的嵌入式文档。像这样:
{
"_id" : ObjectId("5128e567df6232180e00fa7d"),
"values" : {"6" : 482.65},
"day" : 20130203,
}
有一个添加功能的票证可以解决这个问题here,但同时我已经想出了解决这个问题的解决办法。
我做的是,我首先在日期字段上创建 uniqe-index。每当我想要每小时音量时,我就会执行这两个命令。
db.timeseries.insert({day:20130203, values : []}); // Will be rejected if it exists
db.timeseries.update({day:20130203},{$set : {values.6 : 482.65}});
第一个语句试图创建一个新文档 - 并且由于uniqe-index,如果插入已经存在,则它将被拒绝。如果不是,将创建具有用于值字段的嵌入数组的文档。这可确保更新生效。
结果:
{
"_id" : ObjectId("5128e567df6232180e00fa7d"),
"values" : [null,null,null,null,null,null,482.65],
"day" : 20130203,
}
这是我的问题
在生产中,当同时运行这样的几个命令时,我可以确定我的update-command将在我的insert-command之后执行吗? 请注意,我想在不安全模式下运行这两个命令,即我不会等待来自服务器的任何响应。
(从绩效的角度来看这里有关我的工作的评论也很有趣。)
答案 0 :(得分:1)
通常是的,有一种方法可以确保来自客户端的两个请求使用相同的连接。通过使用相同的连接,您可以在服务器上强制执行严格的执行顺序。
实现这一目标的方法因不同的驱动程序而异。
对于Asynchronous Java Driver,您可以从最初的MongoClient实例创建一个“Serialized”MongoClient,它将确保所有请求都使用单个连接。
对于10gen java driver,它会自动(通过ThreadLocal)尝试使用相同的连接。您还可以通过DB.requestStart()/ DB.requestEnd()方法向驱动程序提示,一组命令需要通过管道排列。
startRequest / endRequest适用于大多数10gen驱动程序。另一个例子是PyMongo驱动程序mongo_client有一个start_request() / end_request()对。
答案 1 :(得分:0)
从性能的角度来看,最好只使用一次访问数据库而不是两次。你不能用$ push而不是$ set来更新值字段吗?