Skip to main content

2025-09-28

1. MongoDB Data Structure Design

For your requirements, a two-collection approach in MongoDB is clean, scalable, and highly effective. This separates the concept of the “master document” from its immutable historical versions.
  • documents collection: Stores the master record for each document. It always points to the latest version, acting as the main entry point.
  • documentVersions collection: Stores the immutable, chronological records of each version.

documents Collection Schema

This collection holds one document per callCode. The _id of this document is the unifying callCode. This makes lookups for a specific document very fast.
Field Explanations:
  • _id: (string) The unique, human-readable callCode for the document. Using this as the _id ensures uniqueness and provides a direct lookup key.
  • title: (string) The current title of the document. This can be updated here when a new version is created.
  • latestRevisionNumber: (integer) Caching the latest revision number allows you to quickly know the current version count without querying the other collection.
  • latestVersionId: (ObjectId) A direct reference to the _id of the corresponding document in the documentVersions collection. This creates a fast link to the most recent version’s full details.
  • createdAt: Timestamp of the very first version (revision 0).
  • updatedAt: Timestamp of the most recent version.

documentVersions Collection Schema

This is the core of your version log. Every time a document is saved, a new, immutable document is created in this collection.
Field Explanations:
  • _id: (ObjectId) A unique identifier for this specific version record.
  • documentId: (string) The unifying callCode. This is the most important field for grouping versions. You must create an index on this field.
  • revisionNumber: (integer) The 0-indexed version number. A compound index on (documentId, revisionNumber) would be highly beneficial for performance.
  • changelog: (string) A user-provided message describing the changes in this version.
  • author: (object) Details of the user who created this specific version.
  • storage: (object) An object containing all information needed to retrieve the immutable file from your archival repository (e.g., S3, local filesystem). Including a file hash is crucial for data integrity checks.
  • createdAt: The timestamp when this specific version was created.

How This Design Meets Your Requirements:

  1. View Chronological Change History: This is a simple and efficient query.
  1. View a Specific Version Independently: Each version has its own document and a direct path to its immutable file.
  1. Get the Latest Version: You can either use the documents collection for a very fast lookup or query the documentVersions collection.

2. Exploration with a Graph Database (Neo4j)

A graph database excels at modeling and querying relationships. For version control, this is a very natural fit, creating a “chain” of revisions.

Graph Model

We’ll define Nodes (the entities) and Relationships (how they connect). Nodes:
  • :Document: The conceptual document.
  • Properties: callCode (unique identifier), title.
  • :Version: An immutable version of a document.
  • Properties: revisionNumber, changelog, createdAt, storagePath, hash, etc.
  • :User: The user who created the version.
  • Properties: userId, name.
Relationships:
  • HAS_VERSION: Connects a :Document to all its :Version nodes.
  • PREVIOUS_VERSION: Connects a version to the one that came before it. This forms the chronological linked list.
  • CREATED: Connects a :User to the :Version they created.
  • LATEST_VERSION: A special relationship from a :Document to its most current :Version for fast access.
Visual Representation:

How This Model Meets Your Requirements:

1. View Chronological Change History: You can traverse the PREVIOUS_VERSION chain backwards from the latest version. This is extremely efficient in a graph database. Cypher Query:
2. View a Specific Version Independently: A direct lookup is simple. Cypher Query:

Comparison and Recommendation

Conclusion and Recommendation for Your Stack

For your current requirements and your Laravel/PHP stack, the MongoDB two-collection approach is the most pragmatic and recommended solution.
  • It’s a robust, scalable, and well-understood pattern.
  • Integration with Laravel is seamless with mature packages like jenssegers/mongodb.
  • It perfectly satisfies all your stated needs with simple, performant queries.
The Neo4j exploration is valuable because it shows a powerful alternative. You should seriously consider a graph database if you anticipate your DMS evolving to handle more complex relationships, such as branching/merging, complex approval workflows, or deep analysis of collaboration patterns. For now, MongoDB provides the best balance of power and implementation simplicity.