{"id":21216504,"url":"https://github.com/nodegame/nddb","last_synced_at":"2025-07-10T11:32:25.022Z","repository":{"id":2565946,"uuid":"3545526","full_name":"nodeGame/NDDB","owner":"nodeGame","description":"Javascript lightweight N-dimensional database","archived":false,"fork":false,"pushed_at":"2025-03-05T13:56:26.000Z","size":2295,"stargazers_count":16,"open_issues_count":8,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-03T10:07:14.520Z","etag":null,"topics":["database","javascript","ndimensional-database","nodegame","nosql","select-statements"],"latest_commit_sha":null,"homepage":"http://nodegame.org","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nodeGame.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-02-25T16:02:56.000Z","updated_at":"2024-06-12T07:49:39.000Z","dependencies_parsed_at":"2022-08-06T12:30:15.380Z","dependency_job_id":"6e0b80be-20ac-4479-ad9d-0b7bfebd3df0","html_url":"https://github.com/nodeGame/NDDB","commit_stats":{"total_commits":720,"total_committers":11,"mean_commits":65.45454545454545,"dds":0.1430555555555556,"last_synced_commit":"0da56185349a28d3f85e3b75e704689182d895b7"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/nodeGame/NDDB","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeGame%2FNDDB","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeGame%2FNDDB/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeGame%2FNDDB/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeGame%2FNDDB/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nodeGame","download_url":"https://codeload.github.com/nodeGame/NDDB/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nodeGame%2FNDDB/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264573152,"owners_count":23630428,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","javascript","ndimensional-database","nodegame","nosql","select-statements"],"created_at":"2024-11-20T21:52:49.235Z","updated_at":"2025-07-10T11:32:24.722Z","avatar_url":"https://github.com/nodeGame.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NDDB\n\n[![Build Status](https://travis-ci.org/nodeGame/NDDB.png?branch=master)](https://travis-ci.org/nodeGame/NDDB)\n\nNDDB is a powerful and versatile object database for node.js and the browser.\n\n---\n\nNDDB (N-Dimensional DataBase) supports indexes, views, hashes, joins,\ngroup-by, basic statistics, custom operations, saving and loading from\nfile system and browser localStorage, and much more.\n\nDeveloper-friendly thanks to an easy api, detailed documentation, and\nwide test coverage.\n\n## List of features\n\n- Selecting: `select`, `and`, `or`\n- Sorting: `sort`, `reverse`, `last`, `first`, `limit`, `distinct`,\n  `shuffle`\n- Indexing: `view`, `index`, `hash`, `comparator`\n- Custom callbacks: `map`, `each`, `filter`\n- Updating and Deletion: `update`, `remove`, `clear`\n- Advanced operations: `split`, `join`, `concat`, `groupBy`\n- Fetching and transformations: `fetch`, `fetchArray`,\n  `fetchKeyArray`, `fetchValues`, `fetchSubObj`\n- Statistics operator: `count`, `max`, `min`, `mean`, `stddev`\n- Diff: `diff`, `intersect`\n- Skim: `skim`, `keep`\n- Iterator: `previous`, `next`, `first`, `last`\n- Tagging: `tag`\n- Event listener / emitter: `on`, `off`, `emit`\n- Saving and Loading: `save`, `saveSync`, `load`, `loadSync`, `setWD`, `getWD`, `loadDir`, `loadDirSync`\n\n\u003c!-- The complete NDDB api documentation is available\n[here](http://nodegame.github.com/NDDB/docs/nddb.js.html). --\u003e\n\n## Usage\n\nLoad the library in Node.js:\n\n```javascript\nconst NDDB = require('NDDB');\n\n// Backward-compatible mode.\n// const NDDB = require('NDDB').NDDB;\n```\n\nor in the browser add a script tag in the page:\n\n```html\n\u003c!-- Must load a version of NDDB that includes JSUS (see 'build/' dir) --\u003e\n\u003cscript src=\"/path/to/nddb.js\"\u003e\u003c/script\u003e\n```\n\nCreate an instance of NDDB:\n\n```javascript\nlet db = NDDB.db();\n// let db = new NDDB(); // legacy\n```\n\nInsert an item into the database:\n\n```javascript\n// Add one item to the database.\ndb.insert({\n    painter: \"Picasso\",\n    title: \"Les Demoiselles d'Avignon\",\n    year: 1907\n});\n```\n\nImport a collection of items:\n\n```javascript\nlet items = [\n    {\n        painter: \"Dali\",\n        title: \"Portrait of Paul Eluard\",\n        year: 1929,\n        portrait: true\n    },\n    {\n        painter: \"Dali\",\n        title: \"Barcelonese Mannequin\",\n        year: 1927\n    },\n    {\n        painter: \"Monet\",\n        title: \"Water Lilies\",\n        year: 1906\n    },\n    {\n        painter: \"Monet\",\n        title: \"Wheatstacks (End of Summer)\",\n        year: 1891\n    },\n    {\n        painter: \"Manet\",\n        title: \"Olympia\",\n        year: 1863\n    }\n];\n\n// Import an array of items at once.\ndb.importDB(items);\n```\n\nRetrieve the database size:\n\n```javascript\ndb.size(); // 6\n```\n\n### Select Items\n\nSelect statements begin with `select` and can be refined with\n`and` and `or` statements. Select statements accept three input parameters:\n\n  - 'property'\n  - 'operator'\n  - any additional number of arguments required by operator\n\nBasic operators include standard logical operators:\n\n   - `=`, `==`, `!=`, `\u003e`, `\u003e=`, `\u003c`, `\u003c=`,\n\nAdvanced comparison operators include:\n\n   - `E`: field exists (can be omitted, it is the default one)\n   - `\u003e\u003c`: between values (expects an array as third parameter)\n   - `\u003c\u003e`: not between values (expects an array as third parameter)\n   - `in`: element is found in array (expects an array as third parameter)\n   - `!in`: element is noi found in array (expects an array as third parameter)\n   - `LIKE`: string SQL LIKE (case sensitive)\n   - `iLIKE`: string SQL LIKE (case insensitive)\n\nIt is possible to access and compare nested properties simply\nseparating them with `.`.\n\n#### Select Examples\n\nSelect all paintings from Dali:\n\n```javascript\ndb.select('painter', '=', 'Dali'); // 2 items\n```\n\nCase sensitive `LIKE` operator:\n\n```javascript\ndb.select('painter', 'LIKE', 'M_net'); // 3 items\n```\n\nSelect on multiple properties (`*`) with case insensitive `LIKE`:\n\n```javascript\ndb.select('*', 'iLIKE', '%e%'); // All items\ndb.select(['painter', 'portrait'], 'iLIKE', '%e%') // 5 items\n```\n\nSelect all portraits:\n\n```javascript\n// Property 'portrait' must not be undefined.\ndb.select('portrait'); // 1 item\n```\n\nSelect all paintings from Dali that are before 1928:\n\n```javascript\ndb.select('painter', '=', 'Dali')\n  .and('year', '\u003c', 1928); // 1 item\n```\n\nSelect all paintings of the beginning of XX's century:\n\n```javascript\ndb.select('year', '\u003e\u003c', [1900, 1910]) // 2 items\n```\n\n### Fetching items\n\nSelect statements are not evaluated until a `fetch` statement is invoked, returning the array of selected items, and preventing further chaining.\n\n```javascript\ndb.select('painter', '=', 'Dali').fetch();\n\n// [\n// {\n//     painter: \"Dali\",\n//     title: \"Portrait of Paul Eluard\",\n//     year: 1929,\n//     portrait: true\n// },\n// {\n//     painter: \"Dali\",\n//     title: \"Barcelonese Mannequin\",\n//     year: 1927\n// }\n// ]\n```\n\nOther fetch methods can manipulate the items before they are returned.\n\n```javascript\n// Create a new database without the items by Picasso.\nlet newDb = db.select('painter', '!=', 'Picasso').breed();\n\n// fetchValues\n//\n// Fetch all the values of specified properties and return them in an object.\nnewDb.fetchValues(['painter', 'title']);\n\n// {\n//   painter: [ 'Dali', 'Dali', 'Monet', 'Monet', 'Manet' ],\n//   year: [ 1929, 1927, 1906, 1891, 1863 ]\n// }\n\n// fetchSubObj\n//\n// Keeps only specified properties in the objects, before returning them in\n// an array (items in the original database are NOT modified).\nnewDb.fetchSubObj(['painter', 'title']);\n\n// [\n//     {\n//         painter: \"Dali\",\n//         year: 1929\n//     },\n//     {\n//         painter: \"Dali\",\n//         year: 1927\n//     },\n//     {\n//         painter: \"Monet\",\n//         year: 1906\n//     },\n//     {\n//         painter: \"Monet\",\n//         year: 1891\n//     },\n//     {\n//         painter: \"Manet\",\n//         year: 1863\n//     }\n// ]    \n\n// fetchArray\n//\n// Returns the items as arrays.\nnewDb.fetchArray()\n// [\n//  [ 'Dali', 'Portrait of Paul Eluard', 1929, true ],\n//  [ 'Dali', 'Barcelonese Mannequin', 1927 ],\n//  [ 'Monet', 'Water Lilies', 1906 ],\n//  [ 'Monet', 'Wheatstacks (End of Summer)', 1891 ],\n//  [ 'Manet', 'Olympia', 1863 ]\n// ]\n\n\n// fetchKeyArray\n//\n// Returns the items as arrays (including the keys).\nnewDb.fetchKeyArray()\n// [\n//   [\n//     'painter', 'Dali', 'title', 'Portrait of Paul Eluard', 'year',\n//     1929, 'portrait', true\n//   ],\n//   [ 'painter', 'Dali', 'title', 'Barcelonese Mannequin', 'year', 1927 ],\n//   [ 'painter', 'Monet', 'title', 'Water Lilies', 'year', 1906 ],\n//   [\n//     'painter', 'Monet', 'title', 'Wheatstacks (End of Summer)', 'year', 1891\n//   ],\n//   [ 'painter', 'Manet', 'title', 'Olympia', 'year', 1863 ]\n// ]\n```\n\n### Sorting\n\nDefine a global comparator function that sorts all the entries chronologically:\n\n```javascript\ndb.globalCompator = function (o1, o2) {\n    if (o1.year \u003c o2.year) return -1;\n    if (o1.year \u003e o2.year) return 1;\n    return 0;\n};\n```\n\nSort all the items (global comparator function is automatically used):\n\n```javascript\ndb.sort(); // Order: Manet, Monet, Monet, Picasso, Dali, Dali\n```\n\nReverse the order of the items:\n\n```javascript\ndb.reverse(); // Order: Dali, Dali, Picasso, Monet, Monet, Manet\n```\n\nDefine a custom comparator function for the name of the painter, which\ngives highest priorities to the canvases of Picasso:\n\n```javascript\ndb.compare('painter', function (o1, o2) {\n    if (o1.painter === 'Picasso') return -1;\n    if (o2.painter === 'Picasso') return 1;\n});\n```\n\nSort all the paintings by painter using the new comparator:\n\n```javascript\ndb.sort('painter'); // Picasso is always listed first.\n```\n\n### Views\n\nSplits the database in sub-databases, each containing semantically\nconsistent set of entries:\n\n```javascript\n// Let us add some cars to our previous database of paintings.\nlet cars = [\n    {\n      car: \"Ferrari\",\n      model: \"F10\",\n      speed: 350,\n    },\n    {\n      car: \"Fiat\",\n      model: \"500\",\n      speed: 100,\n    },\n    {\n      car: \"BMW\",\n      model: \"Z4\",\n      speed: 250,\n    },\n];\n\n// Default view: returns items with the value\n// of the property 'painter' !== undefined.\ndb.view('painter');\n\n// Make the view function explicit.\ndb.view('art', function(o) {\n  return o.painter;\n});\n\ndb.view('cars', function(o) {\n  return o.car;\n});\n\ndb.rebuildIndexes();\n\ndb.size();          // 9\ndb.painter.size();  // NDDB with 6 art entries\ndb.art.size();      // NDDB with 6 art entries\ndb.cars.size();     // NDDB with 3 car entries\n```\n\n### Hashing\n\nDefine a custom hash function that creates a new view for each of the\npainters in the database:\n\n```javascript\ndb.hash('painter');\n// Or the equivalent explicit function definition.\ndb.hash('painter', function(o) {\n    return o.painter;\n});\n\ndb.rebuildIndexes();\n\ndb.size();          // 6, unchanged;\ndb.painter.Picasso; // NDDB with 1 element in db\ndb.painter.Monet    // NDDB with 2 elements in db\ndb.painter.Manet    // NDDB with 1 elements in db\ndb.painter.Dali     // NDDB with 2 elements in db\n```\n\n### Listening to events\n\nNDDB fires the following events: `insert`, `update`, `remove`, `setwd`, `save`, `load`. Users can listen to these events and modify their behavior.\n\n#### Decorating objects on insert\n\nListen to the `insert` event and modify the inserted items by adding\nan index that is incremented sequentially:\n\n```javascript\nlet id = 0;\nfunction getMyId(){ return id++; };\n\ndb.on('insert', function(item) {\n    item.myId = getMyId();\n});\n```\n\n#### Canceling operations: insert, update, remove.\n\nEvent listeners can block the execution of the operation by returning `false`. No errors are thrown.\n\n```javascript\n// Insert event.\n// Parameters:\n//  - item: the item to insert.\ndb.on('insert', function(item) {\n    if (item.year \u003e 3000) return false; // Item is not added.\n});\n\n// Update event.\n// Parameters:\n//   - item: the item to update.\n//   - update: an object containing the properties to update/add.\n//   - idx: the index of the item in the reference database (note: in a\n//          sub-selection, the index of the item may differ from its index\n//          in the main database.)\ndb.on('update', function(item, update, idx) {\n    if (update.year \u003e 3000) return false; // Item is not updated.\n});\n\n// Remove event.\n// Parameters:\n//   - item: the item to remove.\n//   - idx: the index of the item in the reference database (note: in a\n//          sub-selection, the index of the item may differ from its index\n//          in the main database.)\ndb.on('remove', function(item, idx) {\n    if (item.year \u003c 3000) return false; // Item is not removed.\n});\n```\n\nAttention! The order in which the event listeners are added matters.\nIf an event listener returns `false`, all successive event listeners are skipped.\n\n#### Modifying save/load options.\n\n```javascript\n// Save/load event (both sync or async).\n// Parameters:\n//   - options: object with the user options for the save/load event.\n//   - info: an object containing information about the save/load command,\n//           which cannot be altered. Format:\n//           {\n//               file:     'path/to/file.csv',\n//               format:   'csv',\n//               cb:       function() {},   // User defined function, if any.\n//           }\n//\ndb.on('save', function(options, info) {\n    if (info.format === 'csv') {\n        options.header = [ 'id', 'time', 'action'];  // Modify header.\n    }\n});\n```\n\n#### Intercept changes in working directory\n\n```javascript\n// Set working directory event.\n// Parameters:\n//   - wd: The new working directory.\ndb.on('setwd', function(wd) {\n    // Take note of the change, the value cannot be modified.\n});\n```\n\n### Indexes\n\nDefine a custom indexing function that gives fast, direct access to\nthe items of the database;\n\n```javascript\ndb.index('id');\n// Or the equivalent explicit function definition.\ndb.index('id', function(o) {\n    return o.id;\n});\n\ndb.rebuildIndexes();\n\ndb.id.get(0).name; // Picasso\n\ndb.id.update(0, {\n  comment: \"Good job Pablo!\"\n});\n\n// Counts items in selection.\ndb.select('comment').count(); // 1\n\nlet picasso = db.id.remove(0);\ndb.size(); // (0)\n\n// Get all available keys in the index\ndb.painter.getAllKeys(); // ['0','1', ... ]\n\n// Get all elements indexed by their key in one object\ndb.painter.getAllKeyElements();\n```\n\n#### Default index\n\nThe property `._nddbid` is added to every inserted item. The property\nis not enumerable (if the environment permits it), and all items are\nindexed against it:\n\n\n```javascript\ndb.nddbid.get('123456'); // Returns the item with nddbid equal to 123456.\n```\n\n## Configuration Options\n\n```javascript\nlet logFunc = function(txt, level) {\n  if (level \u003e 0) {\n    console.log(txt);\n  }\n};\n\nlet options = {\n  tags:  {},          // Collection of tags\n  update: {           // On every insert, remove and update:\n    indexes:  true,   // Updates the indexes, if any\n    sort:     true,   // Sorts the items of the database\n    pointer:  true,   // Moves the iterator to the last inserted element\n  },\n  C:  {},             // Collection of comparator functions\n  H:  {},             // Collection of hashing functions\n  I:  {},             // Collection of indexing functions\n  V:  {},             // Collection of view functions\n  log: logFunc,       // Default stdout\n  logCtx: logCtx      // The context of execution for the log function\n  nddb_pointer: 4,    // Set the pointer to element of index 4\n  globalCompare: function(o1, o2) {\n    // Comparator.\n  },\n  filters: {          // Extends NDDB with new operators for select queries\n    '%': function(d, value, comparator) {\n          return function(elem) {\n            if ((elem[d] % value) === 0) {\n              return elem;\n            }\n          }\n      }\n  },\n  share: {           // Contains objects that are copied by reference to\n                     // in every new instance of NDDB.\n    sharedObj: sharedObj\n  }\n}\n\nlet nddb = NDDB.db(options);\n\n// or\n\nnddb = NDDB.db();\nnddb.init(options);\n```\n\n## Saving and Loading Items\n\nThe items in the database can be saved and loaded using the `save` and\n`load` methods, or their synchronous implementations `saveSync` and\n`loadSync`.\n\nThe methods `loadDir` and `loadDirSync` load an entire directory.\n\nThe following formats are available: `csv`, `json`, and `ndjson`.\n\n### Saving and loading to file system (node.js environment)\n\nTwo formats are natively supported: `.json` and `.csv` (automatically\ndetected by the filename's extension. For unknown extensions, NDDB falls\nback to the default format (json, but it can be overridden).\n\nIt is possible to specify new formats using the `addFormat` method.\n\n#### Save/Load Examples\n\n```javascript\n\n// SAVING.\n\n// Saving items in JSON format.\ndb.save('db.json', () =\u003e console.log(\"Saved db into 'db.json'\") );\n\n// Saving items in CSV format.\ndb.save('db.csv', () =\u003e console.log(\"Saved db into db.csv'\") );\n\n// Saving items in CSV format.\ndb.save('db.ndjson', () =\u003e console.log(\"Saved db into db.ndjson'\") );\n\n// Saving items synchronously in CSV format.\ndb.saveSync('db.csv');\nconsole.log(\"Saved db into db.csv'\");\n\n// Saving items in the default format (usually json).\ndb.getDefaultFormat(); // json\ndb.save('db.out', function() {\n    console.log(\"Saved db into db.out'\");\n});\n\n// Specifying the default format and saving into CSV.\ndb.setDefaultFormat('csv');\ndb.save('db.out', function() {\n    console.log(\"Saved db into db.out'\");\n});\n\n// LOADING.\n\n// Loading items into database synchronously.\ndb.loadSync('db.csv');\nconsole.log(\"Loaded csv file into database\");\n\n// Loading 'adapted' items into database.\ndb.load('db.csv', () =\u003e console.log(\"Loaded csv file into database\") );\n\n```\n\n#### Loading an entire directory\n\nThe method `loadDir` and `loadDirSync` load an entire directory.\n\n#### loadDir Options\n\nIn addition to the options of the native load method of the chosen format:\n\n- `recursive`: if TRUE, it will look into sub-directories. Default: FALSE.\n- `maxRecLevel`: the max level of recursion allowed. Default: 10.\n- `filter`: A filter function or a regex expression to apply to every file name.\n- `dirFilter`: A filter function or a regex expression to apply to every directory name.\n- `onError`: What to do in case of errors: 'continue' will skip the file with errors and go to the next one.\n\n```js\n\n// Load files.\nlet opts = {\n  recursive: true,\n  filter: 'bonus',      // All files containing the word 'bonus'.\n  dirFilter: (dir) =\u003e {\n    return !~dir.indexOf(\"skip\"); // Skip if directory contains word 'skip'.\n  };  \n\n  // Alternative filters:\n\n  // filter: file =\u003e file === 'bonus.csv', // Only 'bonus.csv' files.\n  // format: 'csv'     // All 'csv' files.\n};\n\ndb.loadDirSync(DATADIR, opts);\n\n```\n\nNote: `loadDir` is not yet fully async. It loads files into the database asynchronously, but scans for files in the file system synchronously.\n\n#### Adding a New Format\n\n```js\n// Specify a new format.\ndb.addFormat('asd', {\n   save: function(db, file, cb, options) {\n         // save file asynchronously.\n   },\n   load: function(db, file, cb, options) {\n         // load file asynchronously.\n   },\n   saveSync: function(db, file, cb, options) {\n         // save file synchronously.\n   },\n   loadSync: function(db, file, cb, options) {\n         // load file synchronously.\n   }\n});\n\n// Saving in the new format.\ndb.save('db.asd');\n```\n\n### Streaming items to file system (node.js environment)\n\nThe `stream` method automatically save items inserted into the database to the file system.\n\n```js\ndb.stream();\n// Save items to [db name].[default format], for example: 'nddb.json'.\n```\n\n#### Stream options:\n\nThe stream method takes an optional configuration object:\n\n- `format`:   the format: csv, json, ndbjson.\n- `filename`: path to file name (default [db name].[format])\n- `delay`:    milliseconds to wait before copying items to file system (default 10)\n- `journal`:  if TRUE, items are incapsulated in a data structure that contains information about the operation (insert, update, delete).\n\n### Journaling operations to file system (node.js environment)\n\nThe `journal` method keeps track of all operations (not just inserts).\n\n```js\ndb.journal();\n// Save items to [db name].journal, for example: 'nddb.journal'.\n```\nThis method is wrapper for the stream method with the journal flag TRUE.\n\nItems are saved in ndjson format and can they imported in a new database with the `importJournal` method.\n\n```js\ndb.importJournal();\n// All operations (inserts, updates, deletes) replayed.\n```\n\n### CSV Advanced Options\n\n#### Specifying an Adapter\n\n```js\n// Transform items before saving them to CSV format.\n\nlet options = {\n    adapter: {\n\n        // Double all numbers in column \"A\".\n        A: function(item) { return item.A * 2; },\n\n        // Rename a property (must add shorterName to a custom header).\n        shortName: 'muchLongerName'\n    }\n};\n\ndb.save('db2.csv', options, () =\u003e {\n    console.log(\"Saved db as csv into 'db2.csv'\");\n    console.log(\"Numbers in column 'A' were doubled\");\n    console.log(\"Values in column 'shortName' are taken from column 'muchLongerName'\");\n});\n\n\n// Transform items before loading them into database.\n// Loading items into database.\noptions = {\n    adapter: {\n        A: function(item) { return item.A / 2; }\n    }\n};\n\ndb.load('db2.csv', options, () =\u003e {\n   console.log(\"Loaded csv file into database\");\n   console.log(\"Numbers in column 'A' were doubled\");\n});\n```\n\n#### Saving Updates Only\n\nIf you know already when a new set of items are added to the database, you can save incremental updates using the `updatesOnly` flag.\n\n```js\n// Feedback view already created.\ndb.comment.save('comments.csv', {\n\n    // Custom header.\n    header: [ 'timestamp', 'user', 'feedback' ],\n\n    // Saves only updates from previous save command.\n    updatesOnly: true\n});\n```\n\n#### Flatten Items\n\nIf a single user enters multiple items in the database, but you need only one row in the CSV file, you can use the `flatten` flag.\n\n```js\ndb.view('user').save('users.csv', {\n\n    // Custom header.\n    header: [\n        \"user\", \"comment\", \"date\", \"name\", \"last\", \"rating\"\n    ],\n\n    // Merges all items together.\n    flatten: true,\n});\n```\n\nIf you have multiple users in the database, the option `flattenByGroup` will create one CSV row per group (e.g., user).\n\n\n```js\ndb.user.save('users.csv', {\n\n    // Custom header.\n    header: [\n        \"user\", \"comment\", \"date\", \"name\", \"last\", \"rating\"\n    ],\n\n    // Merges all items together.\n    flatten: true,\n\n    // One row per user (can also be a function returning the id of the group).\n    flattenByGroup: 'user',\n});\n```\n\nIn case you need to periodically flatten the items, use the `flatten` option in combination with the `updatesOnly` flag.\n\n### Setting the current working directory (node.js environment)\n\nIt is possible to specify the current working directory to avoid\ntyping long file paths.\n\n```javascript\n// Saving items in JSON format.\ndb.load('/home/this/user/on/that/dir/db.json');\ndb.load('/home/this/user/on/that/dir/db2.json');\ndb.load('/home/this/user/on/that/dir/db3.json');\n\n// Can be shortened to:\ndb.setWD('/home/this/user/on/that/dir');\ndb.load('db.json');\ndb.load('db2.json');\ndb.load('db3.json');\n\n// Get current working directory:\ndb.getWD(); // /home/this/user/on/that/dir/\n```\n\n#### List of all available options\n\n```javascript\n{\n\n    flags: 'w',                     // The Node.js flag to write to fs.\n                                    // Default: 'a' (append).\n\n    encoding: 'utf-8',              // The encoding of the file.\n\n    mode: 0777,                     // The permission given to the file.\n                                    // Default: 0666\n\n    // Options below are CSV ONLY:\n\n    header: true,                   // Loading:\n                                    //  - true: use first line of\n                                    //      file as key names (default)\n                                    //  - false: use [ 'X1'...'XN' ]\n                                    //      as key names;\n                                    //  - array of strings: used as\n                                    //      is as key names;\n                                    //  - array of booleans: selects\n                                    //      key names in order from\n                                    //      columns in csv file\n                                    //\n                                    // Saving:\n                                    //  - true: use keys of first\n                                    //      item as column names (default)\n                                    //  - 'all': collect all keys\n                                    //      from all elements and use\n                                    //      as column names\n                                    //  - function: a callback that\n                                    //      takes each unique key in\n                                    //      the db and returns:\n                                    //      another substitute string,\n                                    //      an array of strings to add,\n                                    //      null to exclude the key,\n                                    //      undefined to keep it.\n                                    //  - false: no header\n                                    //  - array of strings: used as\n                                    //      is for column names (keys\n                                    //      not listed are omitted)\n\n    adapter: {\n        // Update the year property\n        year: function(row) {       // An object containing callbacks for\n            return row['year']-1;   // given csv column names. Callbacks take\n        }                           // an object (a row of the csv file\n    },                              // file on load, or an item of the\n                                    // database on save) and return a value to\n                                    // be saved/loaded under that property name.\n\n    separator: ',',                 // The character used as separator\n                                    // between values. Default ','.\n\n    quote: '\"',                     // The character used as quote.\n                                    // Default: '\"'.\n\n\n    escapeCharacter: '\\\\',          // The char that should be skipped.\n                                    // Default: \\. (load only)\n\n    lineBreak: '\\n',                // Line break character. Default: system's\n                                    // default.\n\n    bufferSize: 128 * 1024,         // Number of bytes to read at once.\n                                    // Default: 128 * 1024.\n\n\n    // SAVE ONLY.\n\n    bool2num: true,                 // If TRUE, booleans are converted to 0/1.\n\n    na: 'NA',                       // Value for missing fields. Default: 'NA'.\n\n    objectLevel: 2,                 // For saving only, the level of nested\n                                    // objects to expand into csv columns\n\n    flatten: true,                  // If TRUE, it flattens all items\n                                    // currently selected into one row.\n\n    flattenByGroup: 'player',       // If set, there will one row per unique\n                                    // value of desired group (here: 'player')\n\n    updatesOnly: true,              // If TRUE, saves only items that were\n                                    // inserted into the database after\n                                    // a file with the same name was last saved.\n\n    updateDelay: 20000,             // Number of milliseconds to wait before\n                                    // saving updates. Default: 10000.\n\n}\n```\n\n\n## Test\n\nNDDB relies on [mocha](http://mochajs.org/) and\n[should.js](http://github.com/visionmedia/should.js) for testing.\n\n    $ npm install # will load all necessary dependencies\n    $ npm test # will run the test suite against nddb.js\n\n## Build\n\nCreate your customized build of NDDB using the make file in the `bin`\ndirectory:\n\n\nIn order to run in the browser NDDB needs to have\n[JSUS](http://github.com/nodeGame/JSUS) loaded. You can include it\nseparately, or create a new build that includes it already. See the\nbuild help for options.\n\n```javascript\nnode make build // Standard build,\nnode make build -a -o nddb-full // Full build\n```\n\nThe build file will be created inside the `build/` directory.\n\n\n## License\n\n[MIT](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodegame%2Fnddb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnodegame%2Fnddb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnodegame%2Fnddb/lists"}