[英]Is there a simpler way to update an entire record in MongoDB using python?
我的用例是这样的:我将一个 json 有效负载传递给一个 python 程序,该程序有条件地将记录插入到我的 MongoDB 集合中。 它检查集合记录中的唯一组合,如果“时间戳”更大,则更新记录,如果未找到组合,则更新记录,如果“时间戳”更低,则保留记录。
payload = {'stCode': 'ABC1', 'skCode': 'CDE2', 'batchCode': 'FGH3', ts: '2022/07/04 09:48:36'}
inp_ts = payload['ts']
inp_ts = datetime.strptime(inp_ts, '%Y/%m/%d %H:%M:%S')
inp_ts_iso = inp_ts.isoformat()
stCode = payload['stCode']
skCode = payload['skCode']
batchCode = payload['batchCode']
result = collection.find_one({'stCode': stCode,'skCode': skCode, 'batchCode': batchCode })
if result is None:
collection.insert_one(payload) #Condition1: Insert record if not present
else:
result_ts = result['ts']
result_ts = datetime.strptime(result_ts, '%Y/%m/%d %H:%M:%S')
result_ts_iso = result_ts.isoformat() #since the date is stored as string in the database
if inp_ts_iso > result_ts_iso:
temps={"storeCode": storeCode,"skuCode": skuCode, "batchCode": batchCode }, {"$set": payload}
collection.update_one(*temps) #Condition2: Update record if timestamp is older
print('Records successfully written to MongoDB')
else:
print("no records written") #Condition3: Do nothing if timestamp is newer
我知道它不是最漂亮的代码,但我希望它更简单、更简短。 有没有办法通过让 Lambda 进行逻辑测试而不是在 Mongo 本身进行测试来实现相同的目标? 我见过复杂的 update_one 查询,但我无法为我的利益工作。 提前致谢!
是的,您可以,您可以通过几种不同的方式进行操作,但它们都涉及使用流水线更新,这允许您在更新中使用聚合运算符。
这是我认为实现这一目标的最优雅的方法:(底部方法的摘要)
const payload = {'stCode': 'ABC1', 'skCode': 'CDE2', 'batchCode': 'FGH3', ts: '2022/07/04 09:48:36'}
const stCode = payload['stCode']
const skCode = payload['skCode']
const batchCode = payload['batchCode']
db.collection.updateOne(
{'stCode': stCode,'skCode': skCode, 'batchCode': batchCode },
[
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$$ROOT",
{
$cond: [
{
$gt: [
"$ts",
payload.ts
]
},
{},
payload
]
}
]
}
}
}
],
{
"upsert": true
}
)
或使用pymongo
:
payload = {'stCode': 'ABC1', 'skCode': 'CDE2', 'batchCode': 'FGH3', ts: '2022/07/04 09:48:36'}
stCode = payload['stCode']
skCode = payload['skCode']
batchCode = payload['batchCode']
collection.update_one(
{'stCode': stCode, 'skCode': skCode, 'batchCode': batchCode},
[
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
"$$ROOT",
{
"$cond": [
{
"$gt": [
"$ts",
payload['ts']
]
},
{},
payload
]
}
]
}
}
}
],
upsert=True
)
所以我们在更新中使用$replaceRoot
,新的根是两个对象的合并。 第一个对象是$$ROOT
参数,所以如果文档不存在它基本上是一个空对象,如果它确实存在那么它是原始对象,这背后的想法是第一个对象是保留_id
字段(以及任何其他必需的预先存在的字段)可能存在于对象上,这就是为什么我们不只在$replaceRoot
中使用新对象,因为它会生成一个新的_id
。
第二个对象基于使用$cond
的条件,如果现有的ts
更大,那么我们使用一个空对象,它不会更改原始$$ROOT
,否则我们只使用新的有效负载,它将覆盖任何现有字段. 如前所述,如果新的有效负载缺少字段,如果可能需要进行一些小的更改,它们将不会被覆盖,但是根据您的代码示例,未处理此潜在的边缘情况,因此我认为它不存在。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.