lodash-id: ID-based Resource Manipulation for Lodash/Lowdb
lodash-id is a utility package that extends Lodash and Underscore with methods for manipulating collections of JavaScript objects based on a unique `id` property, effectively turning them into simple in-memory databases. It provides a set of CRUD-like operations such as `getById`, `insert`, `upsert`, `updateById`, `removeById`, and `removeWhere`. The package normalizes ID comparisons, allowing both string and integer IDs to be treated equivalently since version `0.12.0`. The current stable version is `0.14.1`. Releases are infrequent but address compatibility and feature refinements. Its primary differentiator is its integration as a Lodash mixin, simplifying common data management patterns within existing Lodash-based applications or in conjunction with `lowdb`. It does not handle data persistence directly since `v0.14.0`, delegating that responsibility to `lowdb` or custom implementations.
Common errors
-
TypeError: _.getById is not a function
cause The lodash-id mixin has not been properly applied to the Lodash instance.fixEnsure you have called `_.mixin(require('lodash-id'))` after importing both `lodash` and `lodash-id`. -
Error: Document with id 'X' already exists.
cause You are attempting to use `_.insert` to add a document with an `id` that already exists in the collection.fixIf you intend to replace the existing document, use `_.upsert(collection, document)` instead of `_.insert`. If you wish to only insert new unique documents, ensure the `id` is unique or generated dynamically (e.g., by letting `insert` create one if no ID is provided). -
Data not saved/loaded after application restart or page refresh.
cause You might be expecting `lodash-id` to handle data persistence, but it only provides in-memory array manipulation. Furthermore, `localStorage` and `file` functions were removed in v0.14.0.fixIntegrate your `lodash-id` usage with a dedicated persistence layer like `lowdb` (which is often used with `lodash-id`) or implement your own `save` and `load` mechanisms for the data collections.
Warnings
- breaking As of v0.14.0, `lodash-id` no longer provides `localStorage` or `file` functions for data persistence. Users previously relying on these must now implement custom persistence logic or integrate with `lowdb` directly to handle data saving and loading.
- breaking The behavior of the `insert` method changed significantly. In v0.8.0, `insert` would replace existing documents with the same ID. However, in current versions (post-v0.8.0, likely with the introduction of `upsert`), `insert` now throws an error if a document with the provided ID already exists in the collection. To replace documents, use the `upsert` method instead.
- breaking The `mixWith` function was removed in v0.7.0. Developers must now use `_.mixin` directly to integrate `lodash-id` functionalities into their Lodash instance.
- gotcha Since v0.12.0, `lodash-id` normalizes IDs, treating string and integer representations of the same ID (e.g., `1` and `'1'`) as equivalent in methods like `getById`, `updateById`, and `removeById`. While this simplifies usage, it may lead to unexpected behavior if strict type-based ID comparisons were previously relied upon.
- gotcha By default, `lodash-id` assumes the unique identifier property for documents is `id`. If your documents use a different property (e.g., `_id`, `uuid`), you must explicitly configure `lodash-id` to use that property.
Install
-
npm install lodash-id -
yarn add lodash-id -
pnpm add lodash-id
Imports
- lodash-id mixin
import { getById } from 'lodash-id';const _ = require('lodash'); _.mixin(require('lodash-id')); - getById (and other methods)
const { getById } = require('lodash-id'); const post = getById(db.posts, 1);const post = _.getById(db.posts, 1);
- id (custom ID property)
lodashId.id = '_id';
_.id = '_id';
Quickstart
const _ = require('lodash');
_.mixin(require('lodash-id'));
const db = {
posts: [
{ id: 1, title: 'First Post', published: false },
{ id: 2, title: 'Second Post', published: true }
]
};
// Insert a new document
const newPost = _.insert(db.posts, { title: 'Third Post' });
console.log('Inserted post:', newPost); // { id: 3, title: 'Third Post' }
// Get a document by ID
const post1 = _.getById(db.posts, 1);
console.log('Got post by ID 1:', post1); // { id: 1, title: 'First Post', published: false }
// Update a document by ID
_.updateById(db.posts, newPost.id, { published: true });
console.log('Updated post:', _.getById(db.posts, newPost.id)); // { id: 3, title: 'Third Post', published: true }
// Upsert a document (replaces if ID exists, inserts if not)
_.upsert(db.posts, { id: 1, title: 'First Post Updated', category: 'News' });
console.log('Upserted post 1:', _.getById(db.posts, 1)); // { id: 1, title: 'First Post Updated', category: 'News' }
// Remove a document by ID
const removedPost = _.removeById(db.posts, 2);
console.log('Removed post by ID 2:', removedPost); // { id: 2, title: 'Second Post', published: true }
console.log('Remaining posts:', db.posts); // [{ id: 1, title: 'First Post Updated', category: 'News' }, { id: 3, title: 'Third Post', published: true }]