簡體   English   中英

有沒有更簡單的方法來使用 python 更新 MongoDB 中的整個記錄​​?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM