[英]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.