0
# Document Operations
1
2
Complete CRUD operations for managing documents including insertion, querying, updating, and deletion with MongoDB-style syntax and callback patterns.
3
4
## Capabilities
5
6
### Document Insertion
7
8
Insert single documents or arrays of documents into the database with automatic ID generation and validation.
9
10
```javascript { .api }
11
/**
12
* Insert document(s) into database
13
* @param {object|array} doc - Document or array of documents to insert
14
* @param {function} callback - Callback function (err, insertedDoc) => {}
15
*/
16
insert(doc, callback);
17
```
18
19
**Usage Examples:**
20
21
```javascript
22
const db = new Datastore({ filename: './users.db', autoload: true });
23
24
// Insert single document
25
db.insert({ name: 'Alice', age: 25, email: 'alice@example.com' }, (err, newDoc) => {
26
if (err) {
27
console.error('Insert failed:', err);
28
return;
29
}
30
console.log('Inserted document:', newDoc);
31
// newDoc will have auto-generated _id: { _id: 'random_id', name: 'Alice', age: 25, email: 'alice@example.com' }
32
});
33
34
// Insert multiple documents
35
const users = [
36
{ name: 'Bob', age: 30, role: 'admin' },
37
{ name: 'Charlie', age: 28, role: 'user' },
38
{ name: 'Diana', age: 32, role: 'moderator' }
39
];
40
41
db.insert(users, (err, newDocs) => {
42
if (err) {
43
console.error('Batch insert failed:', err);
44
return;
45
}
46
console.log('Inserted', newDocs.length, 'documents');
47
newDocs.forEach(doc => console.log('- ', doc.name, 'with ID:', doc._id));
48
});
49
50
// Insert with custom _id
51
db.insert({ _id: 'user_001', name: 'Eve', status: 'active' }, (err, newDoc) => {
52
if (!err) {
53
console.log('Document with custom ID:', newDoc._id); // 'user_001'
54
}
55
});
56
57
// Insert with timestamps (if timestampData: true)
58
const timestampDb = new Datastore({
59
filename: './logs.db',
60
timestampData: true,
61
autoload: true
62
});
63
64
timestampDb.insert({ message: 'System startup' }, (err, newDoc) => {
65
if (!err) {
66
console.log('Created at:', newDoc.createdAt);
67
console.log('Updated at:', newDoc.updatedAt);
68
}
69
});
70
```
71
72
### Document Querying
73
74
Find documents using MongoDB-style queries with support for projections and cursor chaining.
75
76
```javascript { .api }
77
/**
78
* Find documents matching query
79
* @param {object} query - MongoDB-style query object
80
* @param {object} projection - Optional field projection object
81
* @param {function} callback - Optional callback function (err, docs) => {}
82
* @returns {Cursor} Cursor for chaining operations if no callback provided
83
*/
84
find(query, projection, callback);
85
86
/**
87
* Find single document matching query
88
* @param {object} query - MongoDB-style query object
89
* @param {object} projection - Optional field projection object
90
* @param {function} callback - Optional callback function (err, doc) => {}
91
* @returns {Cursor} Cursor for chaining operations if no callback provided
92
*/
93
findOne(query, projection, callback);
94
95
/**
96
* Count documents matching query
97
* @param {object} query - MongoDB-style query object
98
* @param {function} callback - Optional callback function (err, count) => {}
99
* @returns {Cursor} Cursor for chaining operations if no callback provided
100
*/
101
count(query, callback);
102
```
103
104
**Usage Examples:**
105
106
```javascript
107
const db = new Datastore({ filename: './users.db', autoload: true });
108
109
// Find all documents
110
db.find({}, (err, docs) => {
111
if (!err) {
112
console.log('All documents:', docs);
113
}
114
});
115
116
// Find with query conditions
117
db.find({ age: { $gte: 18 } }, (err, adults) => {
118
if (!err) {
119
console.log('Adult users:', adults);
120
}
121
});
122
123
// Find with field projection
124
db.find({ role: 'admin' }, { name: 1, email: 1 }, (err, admins) => {
125
if (!err) {
126
// Returns only name, email, and _id fields
127
console.log('Admin users (name/email only):', admins);
128
}
129
});
130
131
// Find one document
132
db.findOne({ name: 'Alice' }, (err, user) => {
133
if (!err && user) {
134
console.log('Found Alice:', user);
135
} else if (!user) {
136
console.log('Alice not found');
137
}
138
});
139
140
// Count documents
141
db.count({ status: 'active' }, (err, count) => {
142
if (!err) {
143
console.log('Active users count:', count);
144
}
145
});
146
147
// Using cursor for chaining (no callback)
148
db.find({ age: { $gte: 18 } })
149
.sort({ age: 1 })
150
.skip(5)
151
.limit(10)
152
.exec((err, docs) => {
153
if (!err) {
154
console.log('Sorted adults (page 2):', docs);
155
}
156
});
157
158
// Complex query with multiple conditions
159
db.find({
160
$and: [
161
{ age: { $gte: 25 } },
162
{ role: { $in: ['admin', 'moderator'] } },
163
{ status: 'active' }
164
]
165
}, (err, docs) => {
166
if (!err) {
167
console.log('Senior staff members:', docs);
168
}
169
});
170
```
171
172
### Document Updates
173
174
Update documents with MongoDB-style update operators and options for multi-document updates and upserts.
175
176
```javascript { .api }
177
/**
178
* Update documents matching query
179
* @param {object} query - MongoDB-style query object to select documents
180
* @param {object} update - Update operations or replacement document
181
* @param {object} options - Update options
182
* @param {function} callback - Callback function (err, numAffected, affectedDocuments, upsert) => {}
183
*/
184
update(query, update, options, callback);
185
186
/**
187
* Update operation options
188
*/
189
interface UpdateOptions {
190
multi?: boolean; // Update multiple documents (default: false)
191
upsert?: boolean; // Insert document if no match found (default: false)
192
returnUpdatedDocs?: boolean; // Return updated documents in callback (default: false)
193
}
194
```
195
196
**Usage Examples:**
197
198
```javascript
199
const db = new Datastore({ filename: './users.db', autoload: true });
200
201
// Update single document with $set operator
202
db.update(
203
{ name: 'Alice' },
204
{ $set: { age: 26, status: 'premium' } },
205
{},
206
(err, numReplaced) => {
207
if (!err) {
208
console.log('Updated', numReplaced, 'document(s)');
209
}
210
}
211
);
212
213
// Update multiple documents
214
db.update(
215
{ role: 'user' },
216
{ $set: { role: 'member' } },
217
{ multi: true },
218
(err, numReplaced) => {
219
if (!err) {
220
console.log('Updated', numReplaced, 'users to members');
221
}
222
}
223
);
224
225
// Upsert (insert if not found)
226
db.update(
227
{ email: 'new@example.com' },
228
{ $set: { name: 'New User', email: 'new@example.com', status: 'pending' } },
229
{ upsert: true },
230
(err, numReplaced, upsertedDoc) => {
231
if (!err) {
232
if (upsertedDoc) {
233
console.log('Inserted new document:', upsertedDoc);
234
} else {
235
console.log('Updated existing document');
236
}
237
}
238
}
239
);
240
241
// Update with return updated documents
242
db.update(
243
{ status: 'pending' },
244
{ $set: { status: 'active', activatedAt: new Date() } },
245
{ multi: true, returnUpdatedDocs: true },
246
(err, numReplaced, updatedDocs) => {
247
if (!err) {
248
console.log('Activated', numReplaced, 'users');
249
updatedDocs.forEach(doc => {
250
console.log('- Activated:', doc.name);
251
});
252
}
253
}
254
);
255
256
// Increment numeric field
257
db.update(
258
{ name: 'Alice' },
259
{ $inc: { loginCount: 1 } },
260
{},
261
(err, numReplaced) => {
262
if (!err) {
263
console.log('Incremented login count for Alice');
264
}
265
}
266
);
267
268
// Add to array
269
db.update(
270
{ name: 'Bob' },
271
{ $push: { tags: 'vip' } },
272
{},
273
(err, numReplaced) => {
274
if (!err) {
275
console.log('Added VIP tag to Bob');
276
}
277
}
278
);
279
280
// Replace entire document (no operators)
281
db.update(
282
{ _id: 'user_001' },
283
{ name: 'Updated User', email: 'updated@example.com', version: 2 },
284
{},
285
(err, numReplaced) => {
286
if (!err) {
287
console.log('Replaced document entirely');
288
}
289
}
290
);
291
```
292
293
### Document Removal
294
295
Remove documents from the database with support for single or multiple document deletion.
296
297
```javascript { .api }
298
/**
299
* Remove documents matching query
300
* @param {object} query - MongoDB-style query object to select documents
301
* @param {object} options - Remove options
302
* @param {function} callback - Callback function (err, numRemoved) => {}
303
*/
304
remove(query, options, callback);
305
306
/**
307
* Remove operation options
308
*/
309
interface RemoveOptions {
310
multi?: boolean; // Remove multiple documents (default: false)
311
}
312
```
313
314
**Usage Examples:**
315
316
```javascript
317
const db = new Datastore({ filename: './users.db', autoload: true });
318
319
// Remove single document
320
db.remove({ name: 'Alice' }, {}, (err, numRemoved) => {
321
if (!err) {
322
console.log('Removed', numRemoved, 'document(s)');
323
}
324
});
325
326
// Remove multiple documents
327
db.remove(
328
{ status: 'inactive' },
329
{ multi: true },
330
(err, numRemoved) => {
331
if (!err) {
332
console.log('Removed', numRemoved, 'inactive users');
333
}
334
}
335
);
336
337
// Remove documents matching complex query
338
db.remove(
339
{
340
$and: [
341
{ lastLogin: { $lt: new Date('2023-01-01') } },
342
{ status: 'pending' }
343
]
344
},
345
{ multi: true },
346
(err, numRemoved) => {
347
if (!err) {
348
console.log('Cleaned up', numRemoved, 'old pending accounts');
349
}
350
}
351
);
352
353
// Remove all documents (clear database)
354
db.remove({}, { multi: true }, (err, numRemoved) => {
355
if (!err) {
356
console.log('Cleared database:', numRemoved, 'documents removed');
357
}
358
});
359
360
// Conditional removal with age check
361
const oneYearAgo = new Date();
362
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
363
364
db.remove(
365
{
366
createdAt: { $lt: oneYearAgo },
367
archived: true
368
},
369
{ multi: true },
370
(err, numRemoved) => {
371
if (!err) {
372
console.log('Removed', numRemoved, 'archived documents older than 1 year');
373
}
374
}
375
);
376
```
377
378
## Document Validation Rules
379
380
- Documents must be valid JavaScript objects
381
- Field names cannot start with `$` (reserved for operators)
382
- Field names cannot contain dots (`.`) as they're used for nested field access
383
- The `_id` field is automatically generated if not provided
384
- `_id` values must be unique within the collection
385
- Maximum document size depends on available memory (no hard limit)
386
- All data types supported by JSON are valid (string, number, boolean, array, object, null)