Counters: Overview
-
RavenDB's distributed counters, Counters for short, are numeric data variables that can be added to documents.
Use a Counter to count anything that needs counting, like:- Sold products
- Voting results
- Any event related to the document
-
Create and manage Counters using API methods, or through the Studio.
-
In this page:
Why use Counters?
-
Convenient counting mechanism
Counters are very easy to manage, using simple API methods or through the Studio.
E.g. Use counters when you want to -- Keep track of the number of times a document has been viewed or rated.
- Count how many visitors from certain countries or regions read a document.
- Continuously record the number of visitors on an event page.
- Avoid having to update the whole document for just a numeric value change.
- Have a need for a high-throughput counter (also see Distributed Values below).
-
Distributed Values
A Counter's value is distributed between cluster nodes.
Among the advantages of this:- The cluster remains available even when nodes crash.
- Any node can provide or modify a Counter's value immediately, without checking or coordinating this with other nodes.
-
High performance, Low resources
A document includes the Counter's name, while the Counter's actual value is kept in a separate location.
Modifying a Counter's value doesn't require the modification of the document itself.
This results in a performant and uncostly operation. -
High-frequency counting
Counters are especially useful when a very large number of counting operations is required,
because of their speed and low resources usage.
For example:- Use Counters for an online election page, to continuously update a Number-Of-Votes Counter for each candidate.
- Continuously update Counters with the number of visitors in different sections of a big online store.
Overview
-
Design
A document's metadata contains only the Counters' names-list for this document.
Counter Values are not kept in the document's metadata, but in a separate location.- Therefore, changes like adding a new counter or deleting an existing counter trigger a document change,
while simply modifying the Counter Value does not.
- Therefore, changes like adding a new counter or deleting an existing counter trigger a document change,
-
Cumulative Counter Actions
- Counter value-modification actions are cumulative, the order in which they are executed doesn't matter.
E.g., It doesn't matter if a Counter has been incremented by 2 and then by 7, or by 7 first and then by 2. - When a Counter is deleted, the sequence of Counter actions becomes non-cumulative and may require special attention.
- Counter value-modification actions are cumulative, the order in which they are executed doesn't matter.
-
Counters and conflicts
-
Counter actions (for either name or value) do not cause conflicts.
- Counter actions can be executed concurrently or in any order, without causing a conflict.
- You can successfully modify Counters while their document is being modified by a different client.
- Counters actions can still be performed when their related documents are in a conflicted state.
-
Counter actions (for either name or value) do not cause conflicts.
-
Counters cost
-
Counters are designated to lower the cost of counting, but do come with a price.
- All the names of a document's Counters are added to its content, increasing its size.
- Counter values occupy storage space.
- Be aware that the negligible amount of resources required by a few Counters,
may become significant when there are many.
A single document with thousands of Counters is probably an indication of a modeling mistake, for example.
-
Counters are designated to lower the cost of counting, but do come with a price.
-
Counter Naming Convention
- Valid characters: All visible characters, including Unicode symbols
- Length: Up to 512 bytes
- Encoding: UTF-8
-
Counter Value
- Valid range: Signed 64-bit integer (-9223372036854775808 to 9223372036854775807)
- Only integer additions are supported (no floats or other mathematical operations).
-
Number of Counters per document
- RavenDB doesn't limit the number of Counters you can create.
- Note that the Counter names are stored in the document metadata and impact the size of the document.
-
HasCounters
Flag- When a Counter is added to a document, RavenDB automatically sets a
HasCounters
Flag in the document's metadata. - When all Counters are removed from a document, the server automatically removes this flag.
- When a Counter is added to a document, RavenDB automatically sets a
Managing Counters
Enabling the Counters Feature
-
Counters management is currently an experimental feature of RavenDB, and is disabled by default.
-
To enable this feature, follow these steps:
- Open the RavenDB server folder, e.g.
C:\Users\Dave\Downloads\RavenDB-4.1.1-windows-x64\Server
- Open settings.json for editing.
- Enable the Experimental Features -
Verify that the json file contains the following line: "Features.Availability": "Experimental" - Save settings.json, and restart RavenDB Server.
- Open the RavenDB server folder, e.g.
Counter Methods and the CountersFor
object
Managing Counters is performed using the CountersFor
Session object.
-
Counter methods:
CountersFor.Increment
: Increment the value of an existing Counter, or create a new Counter if it doesn't exist.CountersFor.Delete
: Delete a Counter.CountersFor.Get
: Get the current value of a Counter.CountersFor.GetAll
: Get all the Counters of a document and their values.
-
Usage Flow:
- Open a session.
-
Create an instance of
CountersFor
.- Either pass
CountersFor
an explicit document ID, -or- - Pass it an entity tracked by the session, e.g. a document object returned from session.query or from session.Load.
- Either pass
- Use Counter methods to manage the document's Counters.
- If you execute Increment or Delete, call
session.SaveChanges
for the action to take effect on the server.
-
Success and Failure:
- As long as the document exists, Counter actions (Increment, Get, Delete etc.) always succeed.
- When a transaction that includes a Counter modification fails for any reason (e.g. a document concurrency conflict), the Counter modification is reverted.
-
CountersFor
Usage Samples
You can UseCountersFor
by explicitly passing it a document ID (without pre-loading the document).
You can also useCountersFor
by passing it the document object.
// Use CountersFor without loading a document // 1. Open a session using (var session = docStore.OpenSession()) { // 2. pass an explicit document ID to the CountersFor constructor var documentCounters = session.CountersFor("products/1-C"); // 3. Use `CountersFor` methods to manage the product document's Counters documentCounters.Delete("ProductLikes"); // Delete the "ProductLikes" Counter documentCounters.Increment("ProductModified", 15); // Add 15 to Counter "ProductModified" var counter = documentCounters.Get("DaysLeftForSale"); // Get "DaysLeftForSale"'s value // 4. Save changes to the session session.SaveChanges(); }
// Use CountersFor by passing it a document object // 1. Open a session using (var session = docStore.OpenSession()) { // 2. Use the session to load a document. var document = session.Load<Product>("products/1-C"); // 3. Create an instance of `CountersFor` // Pass the document object returned from session.Load as a param. var documentCounters = session.CountersFor(document); // 4. Use `CountersFor` methods to manage the product document's Counters documentCounters.Delete("ProductLikes"); // Delete the "ProductLikes" Counter documentCounters.Increment("ProductModified", 15); // Add 15 to Counter "ProductModified" var counter = documentCounters.Get("DaysLeftForSale"); // Get value of "DaysLeftForSale" // 5. Save the changes to the session session.SaveChanges(); }
Managing Counters using Operations
-
In addition to working with the high-level Session, you can manage Counters using the low-level Operations.
-
CounterBatchOperation can operate on a set of Counters of different documents in a single request.