Loading & Editing an existing document

Simple load and edit

Each document is stored as part of a collection, where a collection is a set of documents sharing the same entity type.

Therefore, if you have the id of an existing document (for example the previously saved BlogPost entry), it can be loaded in the following manner:

// blogposts/1 is entity of type BlogPost with Id of 1
BlogPost existingBlogPost = session.Load<BlogPost>("blogposts/1");

Changes can then be made to that object in the usual manner:

existingBlogPost.Title = "Some new title";

Flushing those changes to the document store is achieved in the usual way:

session.SaveChanges();

You don't have to neither call the Store method nor track any changes yourself. RavenDB will do all of that for you.

Note

The entire document is sent to the server with the Id set to the existing document value, this means that the existing document will be replaced in the document store with the new one. Whilst patching operations are possible with RavenDB, the client API by default will always just replace the entire document in its entirety.

More loading options

Non string identifier

We just have shown how to load a document by it's string key. What if a type of you entity's identifier is not a string? The API also exposes an overload of the Load method that takes a parameter which type is ValueType. By default RavenDB allows you to pass there the most common types of identifiers: integer or Guid.

If you have an entity like this:

public class BlogPostWithIntegerId
{
	public int Id { get; set; }
	/*
	 ...
	*/
}

you can load it by specifing an integer value as the identifier:

BlogPostWithIntegerId blogPostWithIntegerId = session.Load<BlogPostWithIntegerId>(1);

Converting to string identifier

Even if your identifier is a string, you can use the Load overload presented here. The client is aware of the ID generation conventions (collectionName/number), so you could load the entity with key blogposts/1 by using the code:

existingBlogPost = session.Load<BlogPost>(1);

In this case, before the load request is sent, first the conventions are applied on the provided id in order to translate it internally to the real document id. More about conventions you will find here. With regards to this topic these ones are applicable:

  • TransformTypeTagNameToDocumentKeyPrefix
  • FindFullDocumentKeyFromNonStringIdentifier
  • IdentityTypeConvertors
  • IdentityPartsSeparator

Loading multiple docs

Another overload of the Load method allows you to get multiple documents by specifying theirs ids:

BlogPost[] blogPosts = session.Load<BlogPost>("blogposts/1",
											  "blogposts/2",
											  "blogposts/3");

The same would work for non string identifiers of course:

BlogPostWithIntegerId[] blogPostsWithInts = session.Load<BlogPostWithIntegerId>(1, 2, 3);

Load by prefix and pattern

Another option to load multiple documents, this time only if theirs ids fulfill the specified criteria, is LoadStartingWith method. As you can guess you can specify a prefix of an identifier to return only documents that match it. For example to get BlogPost entities that ID is of the form blogposts/1* use the following code:

BlogPost[] prefixedResults = session.Advanced.LoadStartingWith<BlogPost>("blogposts/1");

In result you will get posts the following sample ids: blogposts/1, blogposts/10, blogposts/1/Author/Matt etc.

Except from the prefix you are also able to pass the regular expression that the identifiers (after the prefix part) of returned docs have to match. Example:

BlogPost[] prefixedResultsWithMatch = session.Advanced
	.LoadStartingWith<BlogPost>("blogposts/1", "*/Author/*t");

Here we provided the additional criteria, that limits the results only to documents that IDs have the form blogposts/1*/Author/*t for example: blogposts/11/Author/Matt. In the matches parameter you can specify * and ? as special regular expression characters.

Multiple criterias can be separated using |. E.g. If we want to add to our previous results documents with IDs that have the form blogposts/1*/Type/*t for example: blogposts/11/Type/Innovation then following query needs to be executed:

BlogPost[] prefixedResultsWithMultipleMatch = session.Advanced
	.LoadStartingWith<BlogPost>("blogposts/1", "*/Author/*t|*/Type/*t");