【发布时间】:2021-08-14 18:36:33
【问题描述】:
tl;博士
如何最好地管理时间序列增量文档的安全插入?在数据库端强制执行:代码可能会中断和checking documents already in the DB takes long。我是否应该考虑更改架构(我需要执行时间切片查询)?
细节
我有一个时间序列中的股票价格(这里用 TS 集合建模):
# mongosh
db.stocks.insertMany([{
"metadata": [{"instrumentId": 5578}, {"FX": "USD"}],
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
"price": 12.5
}, {
"metadata": [{"instrumentId": 5578}, {"FX": "USD"}],
"timestamp": ISODate("2021-05-18T04:00:00.000Z"),
"price": 11.4
}])
假设我将它反序列化为一个对象,添加今天的价格并将其序列化回来。我现在有
# to handle with pymongo
documents = [{
"metadata": [{"instrumentId": 5578}, {"FX": "USD"}],
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
"price": 12.5
}, {
"metadata": [{"instrumentId": 5578}, {"FX": "USD"}],
"timestamp": ISODate("2021-05-18T04:00:00.000Z"),
"price": 11.4
}, {
"metadata": [{"instrumentId": 5578}, {"FX": "USD"}],
"timestamp": ISODate("2021-05-18T08:00:00.000Z"),
"price": 11.1
}]
选项 1:唯一复合索引
我将它们全部插入 (reversed) 并让重复插入失败。但是,由于相反的性质,在 delta 文档多于一个的情况下,_id 不会被插入时排序。所以,每次查询都需要调用.sort({"timestamp":1})。
此外,如果我想使用时间序列集合 (mongodb>=5.0),则不支持唯一索引。
# mongosh
db.stocks.createIndex({"metadata.InstrumentId":1,"timestamp":1},{"unique":true})
>>> MongoServerError: Unique indexes are not supported on collections clustered by _id
选项 2:更新插入
我重写了现有文档,并且可以添加更新日期。但是,时间序列集合不支持更新。 此外,我必须在 for 循环中调用更新,这应该会降低效率:
for datapoint in datapoints:
db.stocks.update_one(
{
"timestamp": ISODate("2021-05-18T00:00:00.000Z"),
"metadata": [{"instrumentId": 5578}, {"FX": "USD"}, {"lastUpdate": ISODate(now)}]
},
{"$set":{
"price": 12.5
}
},
{"upsert":True})
目前我最好的猜测是选项 1 与正常集合。
更好的想法?
【问题讨论】:
-
_id是一个唯一的时间戳字段(请参阅 ObjectId.getTimestamp(),为什么不使用它?我假设您的timestamp字段设置为“现在”。 -
对了,我忘了说
timestamp不是“现在”,价格可以与当前时间异步写入。 -
选项 1 的改进可以是
my_collection.insert_many(to_insert, ordered=False)为 here。 -
根据您正在编写/更新的文档数量,bulkWrite() 可能值得一看。
标签: mongodb time-series pymongo