
Product
Announcing Precomputed Reachability Analysis in Socket
Socket’s precomputed reachability slashes false positives by flagging up to 80% of vulnerabilities as irrelevant, with no setup and instant results.
nodedb-json
Advanced tools
A lightweight JSON-based database for Node.js with TypeScript support, indexing, and complex query capabilities
nodedb-json is a lightweight JSON file database tool designed for Node.js. It provides an easy-to-use API for setting, reading, querying, updating, and deleting data stored in JSON files. Supports both CommonJS and ES6 module syntax, as well as TypeScript.
npm install nodedb-json
const NodedbJson = require('nodedb-json');
const db = new NodedbJson('path/to/db.json');
db.set('name', 'John Doe');
console.log(db.get('name')); // Outputs: John Doe
import NodedbJson from 'nodedb-json';
const db = new NodedbJson('path/to/db.json');
db.set('name', 'John Doe');
console.log(db.get('name')); // Outputs: John Doe
import NodedbJson from 'nodedb-json';
// Define your data types
interface User {
id: number;
name: string;
age: number;
}
// Create database with options
const db = new NodedbJson<User>('path/to/db.json', {
autoSave: true,
createIfNotExists: true,
defaultValue: { users: [] }
});
// Type-safe operations
db.push('users', { id: 1, name: 'John', age: 30 });
const user = db.find<User>('users', user => user.id === 1);
db.set("key", "value");
const value = db.get("key");
// Update an object
db.update("key", { newField: "newValue" });
// Update an array item
db.update("arrayKey", (item) => item.id === 1, { name: "Updated Name" });
// Delete a key
db.delete("key");
// Delete array items using a predicate
db.delete("arrayKey", (item) => item.id === 1);
// Batch delete array items by specified field
db.delete("arrayKey", [1, 3]); // Deletes items with id 1 and 3
db.delete("arrayKey", ["Alice", "Charlie"], "name"); // Deletes items with name 'Alice' and 'Charlie'
db.push("users", { name: "Bob", age: 30 }).push("users", { name: "Charlie", age: 35 });
db.push("users", [
{ name: "Bob", age: 30 },
{ name: "Charlie", age: 35 },
]);
const item = db.find("arrayKey", (item) => item.id === 2);
const items = db.filter("arrayKey", (item) => item.isActive);
db.batch([
{ method: "set", args: ["config.theme", "dark"] },
{ method: "set", args: ["config.language", "zh-CN"] },
{ method: "push", args: ["logs", { time: new Date().toISOString(), action: "配置更新" }] }
]);
// Configure auto-save
const db = new NodedbJson('path/to/db.json', { autoSave: false });
// Make changes
db.set("key1", "value1");
db.set("key2", "value2");
// Manually save when ready
db.save();
Indexing can significantly improve lookup performance for large datasets:
// Create a unique index on the 'id' field
db.createIndex("users", { field: "id", type: "unique" });
// Create a multi-value index on the 'age' field
db.createIndex("users", { field: "age", type: "multi" });
// Find using index
const user = db.findByField("users", "id", 1);
// Filter using index
const adults = db.filterByField("users", "age", [30, 40, 50]);
// Drop an index when no longer needed
db.dropIndex("users", "age");
query()
method with comprehensive query operationsorderBy()
, paginate()
, count()
, aggregate()
, distinct()
npm run example:query
demonstration scriptfindByField
and filterByField
methods for index-based queriesdelete
method to support batch deletion by specifying a field.push
, find
, and filter
.interface DbOptions {
autoSave?: boolean; // Auto save after each operation (default: true)
createIfNotExists?: boolean; // Create file if it doesn't exist (default: true)
defaultValue?: Record<string, any>; // Default value for new database
enableIndexing?: boolean; // Enable indexing functionality (default: true)
autoIndex?: boolean; // Auto rebuild indexes on start (default: true)
}
set(key, value)
Sets a value in the JSON data.
key
(string): The key to set.value
(any): The value to set.NodedbJson
- The instance of the database for chaining.get(key)
Gets a value from the JSON data.
key
(string): The key to get.any
- The value.has(key)
Checks if a key exists in the JSON data.
key
(string): The key to check.boolean
- True if the key exists, otherwise false.update(key, predicateOrUpdater, updater)
Updates a value in the JSON data.
key
(string): The key to update.predicateOrUpdater
(function|object): The predicate function or updater object.updater
(object) [optional]: The updater object if a predicate function is provided.NodedbJson
- The instance of the database for chaining.delete(key, predicateOrKeys, field)
Deletes a value from the JSON data.
key
(string): The key to delete.predicateOrKeys
(function|string[]) [optional]: The predicate function or array of keys to delete.field
(string) [optional]: The field to match for array deletion. Default is 'id'.NodedbJson
- The instance of the database for chaining.find(key, predicate)
Finds a value in the JSON data.
key
(string): The key to find.predicate
(function): The predicate function to match.any
- The found value.filter(key, predicate)
Filters values in the JSON data.
key
(string): The key to filter.predicate
(function): The predicate function to match.any[]
- The filtered values.push(key, value)
Pushes a value into an array in the JSON data.
key
(string): The key to push to.value
(any|any[]): The value or values to push.NodedbJson
- The instance of the database for chaining.batch(operations)
Executes multiple operations in batch.
operations
(Array<{method: string, args: any[]}>): Array of operations to execute.NodedbJson
- The instance of the database for chaining.save()
Manually save changes to file.
NodedbJson
- The instance of the database for chaining.createIndex(key, indexDefinition)
Creates an index on a field for faster lookups.
key
(string): The collection path to index.indexDefinition
(IndexDefinition): The index definition with field and type.NodedbJson
- The instance of the database for chaining.findByField(key, field, value)
Finds a value by field using an index if available.
key
(string): The key to find.field
(string): The field to match.value
(any): The value to match.any
- The found value.filterByField(key, field, values)
Filters values by field and possible values using an index if available.
key
(string): The key to filter.field
(string): The field to match.values
(any[]): The values to match.any[]
- The filtered values.dropIndex(key, field)
Removes an index.
key
(string): The collection path.field
(string): The field name.NodedbJson
- The instance of the database for chaining.getIndexes()
Gets all index definitions.
Record<string, Record<string, IndexDefinition>>
- The index definitions.NodeDB-JSON supports powerful complex query operations including sorting, pagination, aggregation, and more. All query operations can leverage indexes for optimal performance.
query(key, options)
Executes a complex query with multiple options.
key
(string): The collection path to query.options
(QueryOptions): Query configuration object.QueryResult
- Comprehensive query results with data, pagination, aggregations, and statistics.interface QueryOptions<T = any> {
where?: PredicateFunction<T> | Record<string, any>; // Filter conditions
sort?: SortOption | SortOption[]; // Sorting options
pagination?: PaginationOption; // Pagination settings
aggregation?: AggregationOption[]; // Aggregation operations
select?: string[]; // Field selection (projection)
limit?: number; // Limit results
skip?: number; // Skip records
}
// Find tech department employees, sorted by salary (descending)
const result = db.query('users', {
where: { department: '技术部' },
sort: { field: 'salary', direction: 'desc' }
});
console.log('Found:', result.data.length, 'records');
console.log('Execution time:', result.stats.executionTime, 'ms');
console.log('Used index:', result.stats.usedIndex);
// Sort by department (ascending), then by salary (descending)
const result = db.query('users', {
sort: [
{ field: 'department', direction: 'asc' },
{ field: 'salary', direction: 'desc' }
]
});
// Get page 2 with 5 records per page
const result = db.query('users', {
sort: { field: 'salary', direction: 'desc' },
pagination: { page: 2, pageSize: 5 }
});
console.log('Current page:', result.pagination.currentPage);
console.log('Total pages:', result.pagination.totalPages);
console.log('Has next page:', result.pagination.hasNext);
// Select only specific fields
const result = db.query('users', {
where: { department: '技术部' },
select: ['name', 'salary', 'age'],
sort: { field: 'salary', direction: 'desc' }
});
// Get various statistics
const result = db.query('users', {
aggregation: [
{ type: 'count' }, // Count records
{ type: 'avg', field: 'salary' }, // Average salary
{ type: 'sum', field: 'salary' }, // Total salary
{ type: 'min', field: 'salary' }, // Minimum salary
{ type: 'max', field: 'salary' }, // Maximum salary
]
});
result.aggregations?.forEach(agg => {
console.log(`${agg.type}:`, agg.value);
});
// Group by department
const result = db.query('users', {
aggregation: [
{ type: 'group', groupBy: 'department' }
]
});
const groups = result.aggregations?.[0]?.value as Record<string, any[]>;
Object.entries(groups).forEach(([dept, users]) => {
console.log(`${dept}: ${users.length} employees`);
});
// Complex query combining multiple features
const result = db.query('users', {
where: user => user.department === '技术部' && user.salary > 12000,
sort: { field: 'age', direction: 'asc' },
pagination: { page: 1, pageSize: 10 },
select: ['name', 'age', 'salary'],
aggregation: [
{ type: 'count' },
{ type: 'avg', field: 'salary' }
]
});
console.log('Results:', result.data);
console.log('Total matching records:', result.aggregations?.[0]?.value);
console.log('Average salary:', result.aggregations?.[1]?.value);
For common operations, convenience methods are available:
orderBy(key, sort, limit?)
Quick sorting with optional limit.
// Get top 5 highest paid employees
const topEarners = db.orderBy('users',
{ field: 'salary', direction: 'desc' },
5
);
paginate(key, page, pageSize, where?)
Quick pagination with optional filtering.
// Get first page of sales department
const salesPage = db.paginate('users', 1, 10, { department: '销售部' });
count(key, where?)
Count records with optional filtering.
// Count tech department employees
const techCount = db.count('users', { department: '技术部' });
aggregate(key, aggregations, where?)
Execute aggregations with optional filtering.
// Get tech department salary statistics
const techStats = db.aggregate('users', [
{ type: 'count' },
{ type: 'avg', field: 'salary' },
{ type: 'max', field: 'salary' }
], { department: '技术部' });
distinct(key, field)
Get unique values for a field.
// Get all unique departments
const departments = db.distinct('users', 'department');
console.log('Departments:', departments);
interface QueryResult<T> {
data: T[]; // Query results
pagination?: PaginationInfo; // Pagination details (if used)
aggregations?: AggregationResult[]; // Aggregation results (if used)
stats: {
totalRecords: number; // Total records before filtering
filteredRecords: number; // Records after filtering
executionTime: number; // Query execution time (ms)
usedIndex: boolean; // Whether indexes were used
};
}
MIT
For any questions or feedback, please contact me at douyaj33@gmail.com.
For issues and support, visit the GitHub Issues page.
FAQs
A lightweight JSON-based database for Node.js with TypeScript support, indexing, and complex query capabilities
The npm package nodedb-json receives a total of 1 weekly downloads. As such, nodedb-json popularity was classified as not popular.
We found that nodedb-json demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket’s precomputed reachability slashes false positives by flagging up to 80% of vulnerabilities as irrelevant, with no setup and instant results.
Product
Socket is launching experimental protection for Chrome extensions, scanning for malware and risky permissions to prevent silent supply chain attacks.
Product
Add secure dependency scanning to Claude Desktop with Socket MCP, a one-click extension that keeps your coding conversations safe from malicious packages.