0

我在 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 表示每小时的一个值。所以 position 很重要,因为 position0 = 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,
}

有一张票可以添加一个功能来解决这个问题但同时我想出了一个解决方法来解决这个问题。

我所做的是,我首先在day-field 上创建了一个 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,
}

这是我的问题

在生产中,当这样的几个命令同时运行时,我可以确定我的更新命令将在我的插入命令之后执行吗?请注意,我想在不安全模式下运行这两个命令,即我不会等待来自服务器的任何响应。

(这里从性能的角度评论我的解决方法也很有趣。)

4

2 回答 2

1

通常是的,有一种方法可以确保来自客户端的两个请求使用相同的连接。通过使用相同的连接,您可以在服务器上强制执行严格的顺序。

对于不同的驱动程序,实现这一点的方法是不同的。

对于异步 Java 驱动程序,您可以从初始 MongoClient 实例创建一个“序列化”的 MongoClient,它将确保所有请求都使用单个连接。

对于 10gen java驱动程序,它将自动(通过 ThreadLocal)尝试使用相同的连接。您还可以通过 DB.requestStart()/DB.requestEnd() 方法向驱动程序提示一组命令需要流水线。

startRequest/endRequest 适用于大多数 10gen 驱动程序。作为另一个例子,PyMongo 驱动程序 mongo_client 有一个start_request() /end_request() 对。

于 2013-02-24T15:49:47.283 回答
0

从性能的角度来看,只使用一次访问数据库比使用两次要好。您不能使用 $push 而不是 $set 来更新值字段吗?

于 2013-02-24T16:20:49.697 回答