MongoDB provides several read preferences that can be used to configure how queries are distributed among replica set members. These read preferences control which members a query can read data from and how to balance the read load across the members.
The different read preferences are:
- `primary`: Queries are only routed to the primary node of the replica set. This ensures that the data returned by the query is the current data (like all updates have been applied) and suitable for write operations. The query will not run if the primary cannot be found, which might reduce availability.
- `primaryPreferred`: Queries are first routed to the primary, but if it's not available or the latency is too high, the query is routed to a secondary node. This preference can be useful when the data is likely to be up to date, but some flexibility is still required in case of primary node failures or maintenance.
- `secondary`: Queries are only routed to the secondaries of the replica set. This can be useful for read-heavy workloads and off-loading queries from the primary node, to free it up for write operations. However, queries will be less up to date than those run on a primary, and any data the query relies on that is only available in the primary node will not be visible, causing inconsistent results.
- `secondaryPreferred`: Queries prefer to read from secondary nodes but still tolerates reading from a primary in case of node unavailability. This preference can be useful for read-heavy workloads, particularly if the primary node is expected to be busy or difficult to reach due to network latency. However, queries may still retrieve inconsistent results if the primary node is missing new data.
- `nearest`: Queries are routed to the node with the lowest network latency from the client. This preference is useful for reducing overall latency and distributing the read load equally among nodes, but it may lead to the read of outdated data, and possibly stale or inconsistent results, and may not be appropriate for writes.
The choice of read preference will depend on the requirements of the application, the use case or the querying patterns. For operations requiring immediate data consistency for updates or inserts, the ‘primary‘ or ‘primaryPreferred‘ read preferences will provide the most accurate data. Meanwhile, when data consistency is not the primary concern, like analytics queries, ‘secondary‘ or ‘secondaryPreferred‘ can be utilized, distributing the read workload across the secondary nodes, while keeping the primary focused on writes.
// Example
// create a Mongo client
const MongoClient = require('mongodb').MongoClient;
const uri = 'mongodb://localhost:27017/test?replicaSet=rs0';
const client = new MongoClient(uri);
// create a collection instance
const collection = client.db('test').collection('inventory');
// insert some test documents
await collection.insertMany([
{item: 'pen', qty: 100},
{item: 'notebook', qty: 200},
{item: 'pencil', qty: 50}
]);
// connect with primary read preference
const primaryReadPref = new MongoClient(client, {
readPreference: 'primary'
});
await primaryReadPref.connect();
// try to read from a secondary with a read preference
const secondaryReadPref = new MongoClient(client, {
readPreference: 'secondaryPreferred'
});
await secondaryReadPref.connect();