ric*_*din 6 time-series upsert mongodb
我正在尝试使用MongoDB 处理时间序列.社区采用的通用解决方案是使用子文档以不同的粒度级别存储信息(请参阅 MongoDB中的时间序列数据的模式设计).
例如,请查看以下文档:
{
timestamp_minute: ISODate("2013-10-10T23:06:00.000Z"),
type: “memory_used”,
values: [
999999, // 1 second
…
1000000, // nth second
1500000, // n+1th second
…
2000000 // 60th
]
}
Run Code Online (Sandbox Code Playgroud)
该文档由分钟信息编制索引,并包含一个子文档,该子文档存储每秒的更详细信息.
到现在为止还挺好.这种方法需要优化才能正常工作:
另一个优化[..]正在为即将到来的时间段预分配所有文件; 这永远不会导致现有文档在磁盘上增长或移动.
要实现上述优化,可以使用$setOnInsert该update方法的属性.
db.getCollection('aCollection').update(
{
timestamp_minute: ISODate("2013-10-10T23:06:00.000Z"),
type: “memory_used”
},
{
$setOnInsert: { values: {'0': 0, '1': 0, '2': 0}},
$inc: {"values.30": 1}
},
{ upsert: true }
)
Run Code Online (Sandbox Code Playgroud)
问题是在两个不同的操作中不可能在同一更新中使用相同的字段.以上更新istruction会生成以下错误:
Cannot update 'values' and 'values.30' at the same time
Run Code Online (Sandbox Code Playgroud)
在此问题上跟踪此问题.
我的问题是:有没有解决方法?我的前缀是我不能使用任何预先分配空文档的批处理,因为我无法先验地知道索引字段的值(在上面的例子中,字段的值type.
提前致谢.
我和我的同事找到了解决方法.我们可以称之为三步初始化.
请记住,MongoDB保证了单个文档的操作原子性.考虑到这一点,我们可以通过以下方式运作:
代码看起来应该类似于以下代码片段.
// Firt of all, try the update
var result = db.test.update(
{timestamp_minute: ISODate("2013-10-10T23:06:00.000Z"), type: “memory_used”},
{$inc: {"values.39": 1}},
{upsert: false}
);
// If the update do not succeed, then try to insert the document
if (result.nModified === 0) {
try {
db.test.insert(/* Put here the whole document */);
} catch (err) {
console.log(err);
}
// Here we are sure that the document exists.
// Retry to execute the update statement
db.test.update(/* Same update as above */);
}
Run Code Online (Sandbox Code Playgroud)
如果前提条件成立,则上述过程有效:_id值应从文档中的其他字段派生.在我们的例子中,_id价值将是'2013-10-10T23:06:00.000Z-memory_used.仅使用此技术,第2点处的插入将正确失败.
| 归档时间: |
|
| 查看次数: |
2384 次 |
| 最近记录: |