MongoDB storage adapter for Keyv
MongoDB storage adapter for Keyv.
Uses TTL indexes to automatically remove expired documents. However MongoDB doesn't guarantee data will be deleted immediately upon expiration, so expiry dates are revalidated in Keyv.
npm install --save keyv @keyv/mongoimport Keyv from 'keyv';
import KeyvMongo from '@keyv/mongo';
const keyv = new Keyv(new KeyvMongo('mongodb://user:pass@localhost:27017/dbname'));
keyv.on('error', handleConnectionError);You can specify the collection name, by default 'keyv' is used.
e.g:
const keyv = new Keyv('mongodb://user:pass@localhost:27017/dbname', { collection: 'cache' });You can also use the createKeyv helper function to create a Keyv instance with KeyvMongo as the store:
import { createKeyv } from '@keyv/mongo';
const keyv = createKeyv('mongodb://user:pass@localhost:27017/dbname');The KeyvMongo constructor accepts a connection URI string or an options object:
// With URI string
const store = new KeyvMongo('mongodb://user:pass@localhost:27017/dbname');
// With options object
const store = new KeyvMongo({
url: 'mongodb://user:pass@localhost:27017/dbname',
collection: 'cache',
db: 'mydb',
useGridFS: false,
});
// With URI string and additional options
const store = new KeyvMongo('mongodb://user:pass@localhost:27017/dbname', { collection: 'cache' });| Option | Type | Default | Description |
|---|---|---|---|
url |
string |
'mongodb://127.0.0.1:27017' |
MongoDB connection URI |
collection |
string |
'keyv' |
Collection name for storage |
namespace |
string | undefined |
undefined |
Namespace prefix for keys |
useGridFS |
boolean |
false |
Whether to use GridFS for storing values |
db |
string | undefined |
undefined |
Database name |
readPreference |
ReadPreference | undefined |
undefined |
MongoDB read preference for GridFS operations |
Any additional options are passed through to the MongoDB driver as MongoClientOptions.
Most configuration options are exposed as properties with getters and setters on the KeyvMongo instance. You can read or update them after construction. Some properties like useGridFS are read-only and can only be set via the constructor.
Get or set the MongoDB connection URI.
- Type:
string - Default:
'mongodb://127.0.0.1:27017'
const store = new KeyvMongo({ url: 'mongodb://user:pass@localhost:27017/dbname' });
console.log(store.url); // 'mongodb://user:pass@localhost:27017/dbname'Get or set the collection name used for storage.
- Type:
string - Default:
'keyv'
const store = new KeyvMongo({ url: 'mongodb://user:pass@localhost:27017/dbname' });
console.log(store.collection); // 'keyv'
store.collection = 'cache';Get or set the namespace for the adapter. Used for key prefixing and scoping operations like clear().
- Type:
string | undefined - Default:
undefined
const store = new KeyvMongo({ url: 'mongodb://user:pass@localhost:27017/dbname' });
store.namespace = 'my-namespace';
console.log(store.namespace); // 'my-namespace'Get whether GridFS is used for storing values. When enabled, values are stored using MongoDB's GridFS specification, which is useful for storing large files. This property is read-only and can only be set via the constructor, because the connection shape differs between GridFS and standard modes.
- Type:
boolean - Default:
false - Read-only (set via constructor only)
const store = new KeyvMongo({ url: 'mongodb://user:pass@localhost:27017/dbname', useGridFS: true });
console.log(store.useGridFS); // trueGet or set the database name for the MongoDB connection.
- Type:
string | undefined - Default:
undefined
const store = new KeyvMongo({ url: 'mongodb://user:pass@localhost:27017', db: 'mydb' });
console.log(store.db); // 'mydb'Get or set the MongoDB read preference for GridFS operations.
- Type:
ReadPreference | undefined - Default:
undefined
import { ReadPreference } from 'mongodb';
const store = new KeyvMongo({
url: 'mongodb://user:pass@localhost:27017/dbname',
useGridFS: true,
readPreference: ReadPreference.SECONDARY,
});
console.log(store.readPreference); // ReadPreference.SECONDARYset(key, value, ttl?) - Set a value in the store.
key(string) - The key to set.value(any) - The value to store.ttl(number, optional) - Time to live in milliseconds. If specified, the key will expire after this duration.- Returns:
Promise<boolean>
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
await keyv.set('foo', 'bar');
await keyv.set('foo', 'bar', 5000); // expires in 5 secondssetMany(entries) - Set multiple values in the store at once.
entries(KeyvEntry[]) - Array of entries to set. Each entry has akey,value, and optionalttlin milliseconds.Valueis inferred from the entries provided.- Returns:
Promise<boolean[]>- An array of booleans indicating whether each entry was set successfully.
In standard mode, uses a single unordered MongoDB bulkWrite operation for efficiency with per-entry error tracking — if individual writes fail, only those entries return false. In GridFS mode, each entry is set individually in parallel using Promise.allSettled, providing per-entry success tracking.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
const results = await keyv.set([
{ key: 'key1', value: 'value1' },
{ key: 'key2', value: 'value2', ttl: 5000 },
]); // [true, true]get(key) - Get a value from the store.
key(string) - The key to retrieve.- Returns:
Promise<any>- The stored value, orundefinedif the key does not exist.
In GridFS mode, get also updates the lastAccessed timestamp on the file, which is used by clearUnusedFor.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
await keyv.set('foo', 'bar');
const value = await keyv.get('foo');
console.log(value); // 'bar'
const missing = await keyv.get('nonexistent');
console.log(missing); // undefinedgetMany(keys) - Get multiple values from the store at once.
keys(string[]) - Array of keys to retrieve.- Returns:
Promise<Array<any>>- Array of values in the same order as the input keys. Missing keys returnundefinedat their position.
In standard mode, uses a single MongoDB query with the $in operator for efficiency. In GridFS mode, each key is fetched individually.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
await keyv.set('key1', 'value1');
await keyv.set('key2', 'value2');
const values = await keyv.get(['key1', 'key2', 'key3']);
console.log(values); // ['value1', 'value2', undefined]has(key) - Check if a key exists in the store.
key(string) - The key to check.- Returns:
Promise<boolean>-trueif the key exists,falseotherwise.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
await keyv.set('foo', 'bar');
console.log(await keyv.has('foo')); // true
console.log(await keyv.has('nonexistent')); // falsehasMany(keys) - Check if multiple keys exist in the store at once.
keys(string[]) - Array of keys to check.- Returns:
Promise<boolean[]>- Array of booleans in the same order as the input keys.
Uses a single MongoDB query with the $in operator for efficiency in both standard and GridFS modes.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
await keyv.set('key1', 'value1');
await keyv.set('key2', 'value2');
const results = await keyv.has(['key1', 'key2', 'key3']);
console.log(results); // [true, true, false]delete(key) - Delete a key from the store.
key(string) - The key to delete.- Returns:
Promise<boolean>-trueif the key was deleted,falseif the key was not found.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
await keyv.set('foo', 'bar');
console.log(await keyv.delete('foo')); // true
console.log(await keyv.delete('nonexistent')); // falsedeleteMany(keys) - Delete multiple keys from the store at once.
keys(string[]) - Array of keys to delete.- Returns:
Promise<boolean[]>- An array of booleans indicating whether each key was deleted.
In standard mode, uses a single MongoDB query with the $in operator. In GridFS mode, all matching files are found and deleted in parallel.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
await keyv.set('key1', 'value1');
await keyv.set('key2', 'value2');
const results = await keyv.delete(['key1', 'key2', 'key3']); // [true, true, false]clear() - Delete all keys in the current namespace.
- Returns:
Promise<void>
Only keys matching the current namespace are removed. If no namespace is set, all keys with an empty namespace are cleared.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store, namespace: 'my-namespace' });
await keyv.set('key1', 'value1');
await keyv.set('key2', 'value2');
await keyv.clear(); // removes all keys in 'my-namespace'iterator() - Iterate over all key-value pairs in the store. The iterator uses the namespace configured on the instance.
- Returns:
AsyncGenerator<[string, any]>- An async generator yielding[key, value]pairs.
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store, namespace: 'ns' });
await keyv.set('key1', 'value1');
await keyv.set('key2', 'value2');
for await (const [key, value] of keyv.iterator()) {
console.log(key, value); // 'key1' 'value1', 'key2' 'value2'
}disconnect() - Close the MongoDB connection.
- Returns:
Promise<void>
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store });
// ... use the store ...
await keyv.disconnect();clearExpired() - Remove all expired files from GridFS. This method only works in GridFS mode and is a no-op that returns false in standard mode.
- Returns:
Promise<boolean>-trueif running in GridFS mode,falseotherwise.
This is useful for manual cleanup of expired GridFS files, since GridFS does not support MongoDB TTL indexes.
const store = new KeyvMongo({ url: 'mongodb://localhost:27017', useGridFS: true });
await store.set('temp', 'data', 1000); // expires in 1 second
// After expiration...
await store.clearExpired(); // removes expired GridFS filesclearUnusedFor(seconds) - Remove all GridFS files that have not been accessed for the specified duration. This method only works in GridFS mode and is a no-op that returns false in standard mode.
seconds(number) - The number of seconds of inactivity after which files should be removed.- Returns:
Promise<boolean>-trueif running in GridFS mode,falseotherwise.
The lastAccessed timestamp is updated each time a file is read via get.
const store = new KeyvMongo({ url: 'mongodb://localhost:27017', useGridFS: true });
await store.set('foo', 'bar');
// Remove files not accessed in the last hour
await store.clearUnusedFor(3600);@keyv/mongo is jumping from v3 to v6 because the entire Keyv monorepo is now unified under a single version number. This approach, similar to what other popular open source projects do, keeps all @keyv/* packages in sync and makes it easier to reason about compatibility across the ecosystem.
The mongodb dependency has been upgraded from ^6.x to ^7.0.0. Review the MongoDB Node.js Driver v7 release notes for any breaking changes that may affect your application.
KeyvMongo no longer extends Node.js EventEmitter. It now extends Hookified, which provides hook-based event management.
// v3 - EventEmitter
const store = new KeyvMongo('mongodb://localhost:27017');
store.on('error', err => console.error(err));
// v6 - Hookified (same usage for basic events)
const store = new KeyvMongo('mongodb://localhost:27017');
store.on('error', err => console.error(err));For most use cases the .on() API is the same, but if you relied on EventEmitter-specific methods like .listenerCount(), .rawListeners(), or .prependListener(), check the Hookified documentation for equivalents.
The useGridFS property can no longer be changed after construction. The connection shape differs between GridFS and standard modes, so this must be set at construction time.
// v3 - Could change after instantiation
const store = new KeyvMongo('mongodb://localhost:27017');
store.useGridFS = true; // worked in v3
// v6 - Must set at construction
const store = new KeyvMongo({ url: 'mongodb://localhost:27017', useGridFS: true });
console.log(store.useGridFS); // true (read-only)The ttlSupport property has been removed. If your code checks for TTL support on the adapter, remove those checks.
The unique index on the underlying MongoDB collection has changed from { key: 1 } to { key: 1, namespace: 1 }. This allows the same key name to exist in different namespaces without conflicts. The old index is automatically dropped and replaced on first connection, so no manual migration is needed.
The constructor options no longer accept arbitrary keys via [key: string]: unknown. Options are now strictly typed with explicit properties. Any additional MongoDB driver options should be valid MongoClientOptions properties.
// v3 - Accepted any properties
const store = new KeyvMongo({ url: 'mongodb://...', customProp: true }); // no type error
// v6 - Strictly typed
const store = new KeyvMongo({ url: 'mongodb://...', collection: 'cache' }); // only known props + MongoClientOptionsA new createKeyv helper simplifies creating a Keyv instance with the MongoDB adapter.
import { createKeyv } from '@keyv/mongo';
// Before
const store = new KeyvMongo('mongodb://localhost:27017');
const keyv = new Keyv({ store, namespace: 'my-ns' });
// After
const keyv = createKeyv({ url: 'mongodb://localhost:27017', namespace: 'my-ns' });Batch set multiple key-value pairs in a single operation using MongoDB bulkWrite.
await store.setMany([
{ key: 'key1', value: 'value1' },
{ key: 'key2', value: 'value2', ttl: 5000 },
]);Check if multiple keys exist in a single query using the $in operator.
const results = await store.hasMany(['key1', 'key2', 'key3']);
// [true, true, false]Manually remove expired files from GridFS storage.
const store = new KeyvMongo({ url: 'mongodb://localhost:27017', useGridFS: true });
await store.clearExpired();Remove GridFS files that have not been accessed for a specified duration.
const store = new KeyvMongo({ url: 'mongodb://localhost:27017', useGridFS: true });
await store.clearUnusedFor(3600); // remove files unused for 1 hour