This is a mongoose plugin for tracking the history and differences of your MongoDB documents. The differences related to one particular model will be stored in a separate MongoDB collection.
yarn add mongoose-history-diff
npm i mongoose-history-diff
Add plugin to your Mongoose schema:
import DiffPlugin from 'mongoose-history-diff';
CoderSchema.plugin(DiffPlugin, {
orderIndependent: true,
diffCollectionName: 'my_diffs',
});
orderIndependent
option defines whether the order of elements in an array is important or not. If true
then it won't create a new diff in case new changes occurred. By default false.
diffCollectionName
option sets the name of a collection with diffs. If not provided ${parent_collection_name}_diffs
will be used.
Here is an example of how would look a diff doc after changing a string field:
// initial state
{
_id: "5f8c17fabb207f0017164033",
name: "John Doe",
}
// after changes
{
_id: "5f8c17fabb207f0017164033",
name: "John Smith",
}
// diff doc
{
dId: "5f8c17fabb207f0017164033",
v: 1,
createdAt: "2020-10-18T10:25:27.279Z",
c: [
{
p: ["name"],
k: "E",
l: "John Doe",
r: "John Smith",
i: null
}
]
}
Diffs are represented as one or more change records (c
field in the doc above). Change record has the following structure:
k
- indicates the kind of change; will be one of the following:N
- indicates that a new field/element was added.D
- indicates that a field/element was deleted.E
- indicates that a field/element was edited.A
- indicates a change within an array.
p
- the field's path in the original document.l
- the value before changing (undefined ifk === 'N'
).r
- the value after changing (undefined ifk === 'D'
).i
- whenk === 'A'
, indicates the index in an array where the change has occurred.it
- whenk === 'A'
, contains a nested change record of an array element with indexi
.
You could exclude specific fields from tracking by adding track_diff: false
configuration to your field definition inside the Mongoose schema:
export const CoderSchema: MongooseSchema<CoderDoc> = new mongoose.Schema(
{
name: {
type: String,
track_diff: false,
},
skills: [
{
name: { type: String }
},
],
{
timestamps: true,
}
);
The _id field is excluded from the tracking by default.
Also, the plugin will add a static diffModel
method to the original model that returns the model of diff collection.
import { type IDiffModel } from 'mongoose-history-diff';
const CoderDiffModel: IDiffModel = Coder.diffModel();
This model contains several static methods (types could be found here):
-
createDiff
method is using internally for creating new diffs, but also exposed in case there will be a necessity to manually save diffs.createDiff(dId: ObjectId, v: number, changes: ChangeDoc[]): Promise<IDiffDoc>;
-
findByDocId
method is using for finding all diffs related to a particular document.findByDocId(dId: ObjectId): Promise<Array<IDiffDoc>>;
-
findAfterVersion
method is using for finding all diffs related to a particular document after specific version.findAfterVersion(dId: ObjectId, v: number): Promise<Array<IDiffDoc>>;
-
findBeforeVersion
method is using for finding all diffs related to a particular document before a specific version.findBeforeVersion(dId: ObjectId, v: number): Promise<Array<IDiffDoc>>;
-
revertToVersion
method is using for reverting a particular document to a specific version.revertToVersion(d: Object, v: number): Promise<any>;
-
mergeDiffs
method is using for getting merged diffs of a particular document among several versions.mergeDiffs(doc: Document, opts?: MergedDiffsOptsT): Promise<Array<RawChangeT>>;