在特定位置嵌入嵌入式阵列 - 我的解决方案是否可以在生产中工作?

时间:2013-02-24 12:59:24

标签: mongodb

我在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 hour1 = 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之后执行吗? 请注意,我想在不安全模式下运行这两个命令,即我不会等待来自服务器的任何响应。

(从绩效的角度来看这里有关我的工作的评论也很有趣。)

2 个答案:

答案 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来更新值字段吗?