Include Revisions
-
Document revisions can be included in results when:
- Making a query (
Session.Query
/Session.Advanced.RawQuery
) - Loading a document (
Session.Load
) from the server
- Making a query (
-
The revisions to include can be specified by:
- Creation time
- Change vector
-
In this page:
Overview
-
Including revisions may be useful, for example, when an auditing application loads or queries for a document.
The document's past revisions can be included with the document to make the document's history available for instant inspection. -
Once loaded to the session, there are no additional trips to the server when accessing the revisions.
Getting a revision that was included with the document will retrieve it directly from the session.
This also holds true when attempting to include revisions but none are found.
-
You can include a single revision by specifying its creation time, see examples below.
-
You can pass local time or UTC, either way the server will convert it to UTC.
-
If the provided time matches the creation time of a document revision, this revision will be included.
-
If no exact match is found, then the first revision that precedes the specified time will be returned.
-
Each time a document is modified, its Change Vector is updated.
-
When a revision is created,
the revision's change vector is the change vector of the document at the time of the revision's creation. -
To include single or multiple document revisions by their change vectors:
-
When modifying the document, store its updated change vector in a property in the document.
Can be done by patching the document from the Client API or from the Studio. -
Specify the path to this property when including the revisions, see examples below.
-
e.g.:
Each time an employee's contract document is modified (e.g. when their salary is raised),
you can add the current change vector of the document to a dedicated property in the document.
Whenever the time comes to re-evaluate an employee's terms and their contract is loaded,
its past revisions can be easily included with it by their change vectors.
-
Include revisions when Loading document
Include a revision by Time
// The revision creation time
// For example - looking for a revision from last month
var creationTime = DateTime.Now.AddMonths(-1);
// Load a document:
var order = session.Load<Order>("orders/1-A", builder => builder
// Pass the revision creation time to 'IncludeRevisions'
// The revision will be 'loaded' to the session along with the document
.IncludeRevisions(creationTime));
// Get the revision by creation time - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = session
.Advanced.Revisions.Get<Order>("orders/1-A", creationTime);
// The revision creation time
// For example - looking for a revision from last month
var creationTime = DateTime.Now.AddMonths(-1);
// Load a document:
var order = await asyncSession.LoadAsync<Order>("orders/1-A", builder => builder
// Pass the revision creation time to 'IncludeRevisions'
// The revision will be 'loaded' to the session along with the document
.IncludeRevisions(creationTime));
// Get the revision by creation time - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = await asyncSession
.Advanced.Revisions.GetAsync<Order>("orders/1-A", creationTime);
Include revisions by Change Vector
// Load a document:
var contract = session.Load<Contract>("contracts/1-A", builder => builder
// Pass the path to the document property that contains the revision change vector(s)
// The revision(s) will be 'loaded' to the session along with the document
.IncludeRevisions(x => x.RevisionChangeVector) // Include a single revision
.IncludeRevisions(x => x.RevisionChangeVectors)); // Include multiple revisions
// Get the revision(s) by change vectors - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = session
.Advanced.Revisions.Get<Contract>(contract.RevisionChangeVector);
var revisions = session
.Advanced.Revisions.Get<Contract>(contract.RevisionChangeVectors);
// Load a document:
var contract = await asyncSession.LoadAsync<Contract>("contracts/1-A",builder => builder
// Pass the path to the document property that contains the revision change vector(s)
// The revision(s) will be 'loaded' to the session along with the document
.IncludeRevisions(x => x.RevisionChangeVector) // Include a single revision
.IncludeRevisions(x => x.RevisionChangeVectors)); // Include multiple revisions
// Get the revision(s) by change vectors - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = await asyncSession
.Advanced.Revisions.GetAsync<Contract>(contract.RevisionChangeVector);
var revisions = await asyncSession
.Advanced.Revisions.GetAsync<Contract>(contract.RevisionChangeVectors);
// Sample Contract document
private class Contract
{
public string Id { get; set; }
public string Name { get; set; }
public string RevisionChangeVector { get; set; } // A single change vector
public List<string> RevisionChangeVectors { get; set; } // A list of change vectors
}
Include revisions when making a Query
Include revisions by Time
// The revision creation time
// For example - looking for revisions from last month
var creationTime = DateTime.Now.AddMonths(-1);
// Query for documents:
var orderDocuments = session.Query<Order>()
.Where(x => x.ShipTo.Country == "Canada")
// Pass the revision creation time to 'IncludeRevisions'
.Include(builder => builder.IncludeRevisions(creationTime))
// For each document in the query results,
// the matching revision will be 'loaded' to the session along with the document
.ToList();
// Get a revision by its creation time for a document from the query results
// It will be retrieved from the SESSION - no additional trip to the server is made
var revision = session
.Advanced.Revisions.Get<Order>(orderDocuments[0].Id, creationTime);
// The revision creation time
// For example - looking for revisions from last month
var creationTime = DateTime.Now.AddMonths(-1);
// Query for documents:
var orderDocuments = await asyncSession.Query<Order>()
.Where(x => x.ShipTo.Country == "Canada")
// Pass the revision creation time to 'IncludeRevisions'
.Include(builder => builder.IncludeRevisions(creationTime))
// For each document in the query results,
// the matching revision will be 'loaded' to the session along with the document
.ToListAsync();
// Get a revision by its creation time for a document from the query results
// It will be retrieved from the SESSION - no additional trip to the server is made
var revision = await asyncSession
.Advanced.Revisions.GetAsync<Order>(orderDocuments[0].Id, creationTime);
Include revisions by Change Vector
// Query for documents:
var orderDocuments = session.Query<Contract>()
// Pass the path to the document property that contains the revision change vector(s)
.Include(builder => builder
.IncludeRevisions(x => x.RevisionChangeVector) // Include a single revision
.IncludeRevisions(x => x.RevisionChangeVectors)) // Include multiple revisions
// For each document in the query results,
// the matching revisions will be 'loaded' to the session along with the document
.ToList();
// Get the revision(s) by change vectors - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = session.
Advanced.Revisions.Get<Contract>(orderDocuments[0].RevisionChangeVector);
var revisions = session
.Advanced.Revisions.Get<Contract>(orderDocuments[0].RevisionChangeVectors);
// Query for documents:
var orderDocuments = await asyncSession.Query<Contract>()
// Pass the path to the document property that contains the revision change vector(s)
.Include(builder => builder
.IncludeRevisions(x => x.RevisionChangeVector) // Include a single revision
.IncludeRevisions(x => x.RevisionChangeVectors)) // Include multiple revisions
// For each document in the query results,
// the matching revisions will be 'loaded' to the session along with the document
.ToListAsync();
// Get the revision(s) by change vectors - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = await asyncSession.
Advanced.Revisions.GetAsync<Contract>(orderDocuments[0].RevisionChangeVector);
var revisions = await asyncSession
.Advanced.Revisions.GetAsync<Contract>(orderDocuments[0].RevisionChangeVectors);
- See the Contract class definition above.
Include revisions when making a Raw Query
-
Use
include revisions
in your RQL when making a raw query. -
Pass either the revision creation time or the path to the document property containing the change vector(s),
RavenDB will figure out the parameter type passed and include the revisions accordingly. -
Aliases (e.g.
from Users as U
) are Not supported by raw queries that include revisions.
Include revisions by Time
// The revision creation time
// For example - looking for revisions from last month
var creationTime = DateTime.Now.AddMonths(-1);
// Query for documents with Raw Query:
var orderDocuments = session.Advanced
// Use 'include revisions' in the RQL
.RawQuery<Order>("from Orders include revisions($p0)")
// Pass the revision creation time
.AddParameter("p0", creationTime)
// For each document in the query results,
// the matching revision will be 'loaded' to the session along with the document
.ToList();
// Get a revision by its creation time for a document from the query results
// It will be retrieved from the SESSION - no additional trip to the server is made
var revision = session
.Advanced.Revisions.Get<Order>(orderDocuments[0].Id, creationTime);
// The revision creation time
// For example - looking for revisions from last month
var creationTime = DateTime.Now.AddMonths(-1);
// Query for documents with Raw Query:
var orderDocuments = await asyncSession.Advanced
// Use 'include revisions' in the RQL
.AsyncRawQuery<Order>("from Orders include revisions($p0)")
// Pass the revision creation time
.AddParameter("p0", creationTime)
// For each document in the query results,
// the matching revision will be 'loaded' to the session along with the document
.ToListAsync();
// Get a revision by its creation time for a document from the query results
// It will be retrieved from the SESSION - no additional trip to the server is made
var revision = await asyncSession
.Advanced.Revisions.GetAsync<Order>(orderDocuments[0].Id, creationTime);
Include revisions by Change Vector
// Query for documents with Raw Query:
var orderDocuments = session.Advanced
// Use 'include revisions' in the RQL
.RawQuery<Contract>("from Contracts include revisions($p0, $p1)")
// Pass the path to the document properties containing the change vectors
.AddParameter("p0", "RevisionChangeVector")
.AddParameter("p1", "RevisionChangeVectors")
// For each document in the query results,
// the matching revisions will be 'loaded' to the session along with the document
.ToList();
// Get the revision(s) by change vectors - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = session.
Advanced.Revisions.Get<Contract>(orderDocuments[0].RevisionChangeVector);
var revisions = session
.Advanced.Revisions.Get<Contract>(orderDocuments[0].RevisionChangeVectors);
// Query for documents with Raw Query:
var orderDocuments = await asyncSession.Advanced
// Use 'include revisions' in the RQL
.AsyncRawQuery<Contract>("from Contracts include revisions($p0, $p1)")
// Pass the path to the document properties containing the change vectors
.AddParameter("p0", "RevisionChangeVector")
.AddParameter("p1", "RevisionChangeVectors")
// For each document in the query results,
// the matching revisions will be 'loaded' to the session along with the document
.ToListAsync();
// Get the revision(s) by change vectors - it will be retrieved from the SESSION
// No additional trip to the server is made
var revision = await asyncSession.
Advanced.Revisions.GetAsync<Contract>(orderDocuments[0].RevisionChangeVector);
var revisions = await asyncSession
.Advanced.Revisions.GetAsync<Contract>(orderDocuments[0].RevisionChangeVectors);
- See the Contract class definition above.
Syntax
// Include a single revision by Time
TBuilder IncludeRevisions(DateTime before);
// Include a single revision by Change Vector
TBuilder IncludeRevisions(Expression<Func<T, string>> path);
// Include an array of revisions by Change Vectors
TBuilder IncludeRevisions(Expression<Func<T, IEnumerable<string>>> path);
Parameters | Type | Description |
---|---|---|
before | DateTime |
|
path | Expression<Func<T, string>> |
|
path | Expression<Func<T, IEnumerable<string>>> |
|
Return value | |
---|---|
TBuilder |
|
Patching the revision change vector
-
To include revisions when making a query or a raw query,
you need to specify the path to the document property that contains the revision change vector(s). -
The below example shows how to get and patch a revision change vector to a document property.
using (var session = store.OpenSession())
{
// Get the revisions' metadata for document 'contracts/1-A'
List<IMetadataDictionary> contractRevisionsMetadata =
session.Advanced.Revisions.GetMetadataFor("contracts/1-A");
// Get a change vector from the metadata
string changeVector =
contractRevisionsMetadata.First().GetString(Constants.Documents.Metadata.ChangeVector);
// Patch the document - add the revision change vector to a specific document property
session.Advanced
.Patch<Contract, string>("contracts/1-A", x => x.RevisionChangeVector, changeVector);
// Save your changes
session.SaveChanges();
}
using (var asyncSession = store.OpenAsyncSession())
{
// Get the revisions' metadata for document 'contracts/1-A'
List<IMetadataDictionary> contractRevisionsMetadata =
await asyncSession.Advanced.Revisions.GetMetadataForAsync("contracts/1-A");
// Get a change vector from the metadata
string changeVector =
contractRevisionsMetadata.First().GetString(Constants.Documents.Metadata.ChangeVector);
// Patch the document - add the revision change vector to a specific document property
asyncSession.Advanced
.Patch<Contract, string>("contracts/1-A", x => x.RevisionChangeVector, changeVector);
// Save your changes
await asyncSession.SaveChangesAsync();
}
- See the Contract class definition above.