简体   繁体   English

在MongoDB中跟踪文档属性更改的最佳方法是什么?

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

I would like to know how to keep track of the values of a document in MongoDB. 我想知道如何在MongoDB中跟踪文档的值。

It's a MongoDB Database with a Node and Express backend. 这是一个具有Node和Express后端的MongoDB数据库。

Say I have a document, which is part of the Patients collection. 假设我有一个文档,它是患者集合的一部分。

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

Then I edit the "objective" property, so the document results like this: 然后,我编辑“ objective”属性,因此文档结果如下:

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

What's the best/most efficient way to keep track of that change? 跟踪更改的最佳/最有效方法是什么? In other words, I would like to know that the "objective" property had the value "Burn fat" in the past, and access it in the future. 换句话说,我想知道“客观”属性在过去具有“燃烧脂肪”的值,并在将来使用它。

Thanks a lot! 非常感谢!

Maintain it as a sub-document like below 将其维护为如下所示的子文档

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

}

You can also maintain it as an array field but remember, mongodb doesn't allow you to maintain uniqueness in an array field and if you plan to index the "objective" field, you'll have to create a multi key index 您也可以将其维护为数组字段,但是请记住,mongodb不允许您在数组字段中保持唯一性,并且如果您计划对“ objective”字段建立索引,则必须创建一个多键索引

Maybe you can change the type of "objective" to array and track the changes in it. 也许您可以将“目标”的类型更改为数组并跟踪其中的更改。 the last one of the array is the latest value. 数组的最后一个是最新值。

I think the simplest solution would be to use and update an array: 我认为最简单的解决方案是使用和更新数组:

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 }
  }],
});

Then when you want to update the objective... 然后,当您要更新目标时...

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() });
  }
};

Document will look like: 文档将如下所示:

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
]

Alternatively, if you're worried about document size, then create a separate schema for patient history and reference the user's id (or just store the patient's _id as a string instead of referencing an ObjectId, whichever you prefer): 另外,如果您担心文档的大小,则可以为患者历史记录创建一个单独的架构,并引用用户的ID(或仅将患者的_id存储为字符串,而不是引用ObjectId,这取决于您的偏好):

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

Then create a new patient history document when the objective is updated... 然后在目标更新时创建一个新的患者历史记录文档...

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

And if you need to access to the patient history documents... 如果您需要访问病史文档...

PatientHistory.find({ _id });

Maintaining/tracking history in the same document is not all recommended. 不建议在同一文档中维护/跟踪历史记录。 As the document size will keep on increasing leading to 随着文档大小的不断增加,导致

  • probably if there are too many updates, 16mb document size limit 如果更新太多,文档大小限制为16mb
  • Performance degrades 性能下降

Instead, you should maintain a separate collection for history. 相反,您应该为历史记录维护一个单独的集合。 You might have use hibernates' Javers or envers for auditing for your relational databases. 您可能使用过休眠的Javers或envers来审核关系数据库。 if not you can check how they work. 如果没有,您可以检查它们的工作方式。 A separate table (xyz_AUD) is maintained for each table (xyz). 每个表(xyz)维护一个单独的表(xyz_AUD)。 For each row (with primary key abc) in xyz table, there exist multiple rows in xyz_AUD table, where each row is version of that row. 对于xyz表中的每一行(具有主键abc),xyz_AUD表中都存在多行,其中每一行都是该行的版本。

Moreover, Javers also support MongoDB auditing. 此外,Javers还支持MongoDB审核。 If you are using java you can directly use it. 如果您使用的是Java,则可以直接使用它。 No need to write your own logic. 无需编写自己的逻辑。

Refer - https://nullbeans.com/auditing-using-spring-boot-mongodb-and-javers/ 请参阅-https: //nullbeans.com/auditing-using-spring-boot-mongodb-and-javers/

One more thing, Javers Envers Hibernate are java libraries. Javers Envers Hibernate是Java库。 But I'm sure for other programming languages also, similar libraries will be present. 但我敢肯定,对于其他编程语言,也会有类似的库。

There is a mongoose plugin as well - 还有一个猫鼬插件-

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 跟踪实时通知发送给用户的最佳方法是什么? - What's the best way to keep track of live notifications to send to a user? 将对象属性链接到值的最佳方法是什么? - What's the best way to keep an object property linked to a value? 进行原型制作时跟踪javascript对象引用的最佳方法是什么 - What the best way to keep track of a javascript object reference when prototyping 跟踪Jquery和CSS标识符的最佳方法是什么? - What is the best way keep track of your identifiers for your Jquery and CSS? 通过javascript跟踪表单中的更改的最佳方法是什么? - What is the best way to track changes in a form via javascript? 跟踪 View 状态信息的推荐方法是什么? - What is the recommended way(s) to keep track of View state information? React 跟踪对象数组更改的最佳方式 - React best way to track changes to an array of objects 跟踪从自动建议文本框中选择的元素的ID的最佳方法是什么? - What is the best way to keep track of the id of an element selected from an auto-suggest textbox? 将用户更改保存到 HTML 应用程序的最佳方法是什么? - What is the best way to save a user's changes to a HTML app? 用图表和高质量创建pdf文档的最佳方法是什么? - What's the best way to create a pdf document with charts and in a decent quality?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM