簡體   English   中英

在MongoDB中跟蹤文檔屬性更改的最佳方法是什么?

[英]What is the best way to keep track of changes of a document's property in MongoDB?

我想知道如何在MongoDB中跟蹤文檔的值。

這是一個具有Node和Express后端的MongoDB數據庫。

假設我有一個文檔,它是患者集合的一部分。

{
    "_id": "4k2lK49938d82kL",
    "firstName": "John",
    "objective": "Burn fat"
}

然后,我編輯“ objective”屬性,因此文檔結果如下:

{
    "_id": "4k2lK49938d82kL",
    "firstName": "John",
    "objective": "Gain muscle"
}

跟蹤更改的最佳/最有效方法是什么? 換句話說,我想知道“客觀”屬性在過去具有“燃燒脂肪”的值,並在將來使用它。

非常感謝!

將其維護為如下所示的子文檔

{
    "_id": "4k2lK49938d82kL",
    "firstName": "John",
    "objective": {
        obj1: "Gain muscle",
        obj2: "Burn fat"
    }

}

您也可以將其維護為數組字段,但是請記住,mongodb不允許您在數組字段中保持唯一性,並且如果您計划對“ objective”字段建立索引,則必須創建一個多鍵索引

也許您可以將“目標”的類型更改為數組並跟蹤其中的更改。 數組的最后一個是最新值。

我認為最簡單的解決方案是使用和更新數組:

const patientSchema = new Schema({
  firstName: { type: String, required: true },
  lastName: { type: String, required: true },
  objective: { type: String, required: true }
  notes: [{
    date: { type: Date, default: Date.now() },
    note: { type: String, required: true }
  }],
});

然后,當您要更新目標時...

const updatePatientObjective = async (req, res) => {
  try {
    // check if _id and new objective exist in req.body
    const { _id, objective, date } = req.body;
    if (!_id || !objective) throw "Unable to update patient's objective.";

    // make sure provided _id is valid
    const existingPatient = await Patient.findOne({ _id });
    if (!existingPatient) throw "Unable to locate that patient.";

    // pull out objective as previousObjective 
    const { objective: previousObjective } = existingPatient;

    // update patient's objective while pushing 
    // the previous objective into the notes sub document
    await existingPatient.updateOne({ 
        // update current objective
        $set { objective },
        // push an object with a date and note (previouseObjective) 
        // into a notes array
        $push: { 
          notes: {
            date,
            note: previousObjective              
         },
        },  
      }),
    );

    // send back response
    res
      .status(201)
      .json({ message: "Successfully updated your objective!" });
  } catch (err) {
    return res.status(400).json({ err: err.toString() });
  }
};

文檔將如下所示:

firstName: "John",
lastName: "Smith",
objective: "Lose body fat.",
notes: [
  {
    date: 2019-07-19T17:45:43-07:00,
    note: "Gain muscle".
  },
  { 
    date: 2019-08-09T12:00:38-07:00,
    note: "Work on cardio."
  }
  { 
    date: 2019-08-29T19:00:38-07:00,
    note: "Become a fullstack web developer."
  }
  ...etc
]

另外,如果您擔心文檔的大小,則可以為患者歷史記錄創建一個單獨的架構,並引用用戶的ID(或僅將患者的_id存儲為字符串,而不是引用ObjectId,這取決於您的偏好):

const patientHistorySchema = new Schema({
  _id: { type: Schema.Types.ObjectId, ref: "Patient", required: true },
  objective: { type: String, required: true }
});

然后在目標更新時創建一個新的患者歷史記錄文檔...

PatientHistory.create({ _id, objective: previousObjective });

如果您需要訪問病史文檔...

PatientHistory.find({ _id });

不建議在同一文檔中維護/跟蹤歷史記錄。 隨着文檔大小的不斷增加,導致

  • 如果更新太多,文檔大小限制為16mb
  • 性能下降

相反,您應該為歷史記錄維護一個單獨的集合。 您可能使用過休眠的Javers或envers來審核關系數據庫。 如果沒有,您可以檢查它們的工作方式。 每個表(xyz)維護一個單獨的表(xyz_AUD)。 對於xyz表中的每一行(具有主鍵abc),xyz_AUD表中都存在多行,其中每一行都是該行的版本。

此外,Javers還支持MongoDB審核。 如果您使用的是Java,則可以直接使用它。 無需編寫自己的邏輯。

請參閱-https: //nullbeans.com/auditing-using-spring-boot-mongodb-and-javers/

Javers Envers Hibernate是Java庫。 但我敢肯定,對於其他編程語言,也會有類似的庫。

還有一個貓鼬插件-

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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