是否有一种更简单的方法可以使用Python在MongoDB中更新整个记录?
我的用例是:我将JSON有效载荷传递到Python程序中,该程序将记录列入我的MongoDB集合。它检查集合记录中的唯一组合,并在“时间戳”更大的情况下更新记录,如果找不到组合并保留“ Timestamp”较低的组合,则UPSERTS。
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查询,但我无法为自己的利益而工作。提前致谢!
My use case is this: I am passing a json payload into a python program which conditionally upserts the record into my MongoDB collection. It checks for a unique combination in the collections records and updates the record if the 'timestamp' is greater, upserts if the combination is not found and retains the record if 'timestamp' is lower.
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
I know that it isn't the prettiest of the code but I would like it to be more simple and short. Is there a way of achieving the same by without having Lambda to do the logic test but rather do it on Mongo's side itself? I have seen complex update_one queries but I couldn't work it for my benefit. Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
是的,您可以,您可以以几种不同的方式进行操作,但是它们都涉及管道更新,您可以在更新中使用聚合操作员。
我认为这是实现这一目标的最优雅方法:(底部的方法摘要)
或
pymongo
:mongo playground
因此,我们在更新中使用
$替换
新的根是两个对象的合并。第一个对象是
$$ root
参数,因此,如果文档不存在,则基本上是一个空对象,如果它确实存在,则是原始对象,这是第一个对象的想法是保留对象上可能存在的_id
字段(以及任何其他必需的PER现有字段),这就是为什么我们不仅在$ $替换
中使用新对象因为它将产生一个新的_id
。第二个对象是基于使用
$ cond
的条件,如果现有ts
更大,那么我们使用一个空对象,该对象不会更改原始$$ root
,否则我们只使用新的有效载荷,该有效载荷将覆盖任何现有字段。如前所述,如果新的有效负载缺少字段,则如果可能需要进行一些较小的更改,则不会被覆盖,但是基于您的代码示例,该潜在的边缘案例没有处理,因此我认为它不存在。Yes you can, you can do it in a few different ways, but they all involve using pipelined updates which allows you to use aggregation operators in your updates.
Here is what I consider to be the most elegant way of achieving this: (summary of the approach at the bottom)
Or with
pymongo
:Mongo Playground
So we use
$replaceRoot
in the update, the new root is a merge of two objects.The first object is the
$$ROOT
parameter, so if the document does not exist it's basically an empty object, if it does exist then it's the original object, the idea behind this being the first object is to preserve the_id
field (and any other required pre existing fields) that could exist on the object, this is why we don't just use the new object in the$replaceRoot
as it will generate a new_id
.The second object is based on a condition using
$cond
, if the existingts
is bigger then we use an empty object, which does not change the original$$ROOT
, else we just use the new payload which will overwrite any of the existing fields. As mentioned if the new payload has missing fields they will not be overwritten if this could be the case some minor changes need to be done, but based on your code sample this potential edge case was not handled so I assumed it does not exist.