The record
const Notes = db.collection("notes");
const note = Notes.create({ title: "hi", n: 1, tags: ["a"], done: false });
note.title; // "hi"
note._version; // 1
note.title = "new";
note.dirty(); // true
note.save(); // true
note.dirty(); // false
note._version; // 2
Notes.get(note._id).title; // "new"
Notes.get(note._id) instanceof Notes; // true
save() writes only what changed and answers true. A stored row is guarded by
its _version: if the document changed since the row was read, save() throws
ConflictError and writes nothing (reload() and assign again).
Methods
const Notes = db.collection("notes2");
const rec = Notes.create({ title: "hi", n: 1, tags: ["a"], done: false, tmp: 1 });
rec.has("title"); // true
rec.keys().includes("title"); // true
rec.typeOf("n"); // "number"
rec.set("title", "x") === rec; // true
rec.merge({ n: 5, extra: "e" }) === rec; // true
rec.inc("n", 2).n; // 7
rec.push("tags", "b").tags; // ["a", "b"]
rec.pull("tags", "a").tags; // ["b"]
rec.toggle("done").done; // true
rec.unset("tmp").tmp; // undefined
rec.dirty(); // true
rec.save(); // true
Notes.get(rec._id).tags; // ["b"]
rec.title = "oops";
rec.reload().title; // "x"
rec.title = "oops";
rec.revert().title; // "x"
JSON.parse(JSON.stringify(rec)).title; // "x"
rec.delete(); // true
Notes.get(rec._id); // null
| Method | Does |
|---|---|
save() |
writes the changes; true |
reload(), revert() |
re-read the stored document, dropping unsaved changes |
delete() |
delete the document; true when it existed |
set(field, value) |
an unsaved write; chainable |
merge(object) |
set for each field of the object; chainable |
unset(field) |
remove a field; chainable |
inc(field, n) |
exact add; a BigInt past 2^53; TypeError for a non-number, RangeError past int64 |
toggle(field) |
flip a boolean |
push(field, v), pull(field, v) |
array edits, saved as $push and $pull |
has(field), typeOf(field), keys() |
the field exists, its type name, its field names |
dirty() |
there are unsaved changes |
toJSON() |
the stored document (JSON.stringify(row)) |
The methods change the row in memory; save() writes them. A method name wins
over a stored field of the same name (read such a field through toJSON()).
No method is named type: a stored field named type reads and writes as any
other field.
Detached rows
const Notes = db.collection("notes3");
const draft = new Notes({ title: "draft" });
"_id" in draft; // false
draft.save(); // true
draft._version; // 1
Notes.count(); // 1
new Collection({ ... }) copies the object's own fields. Nothing is stored
until save(), which inserts and fills _id and _version on the same object.
A failed insert (UniqueError) leaves the row detached: fix it and save again.
Query results
const Notes = db.collection("notes4");
Notes.insertMany([{ title: "a", n: 1 }, { title: "b", n: 2 }, { title: "c", n: 3 }]);
const rows = Notes.gt("n", 0).sort("n").all();
rows.length; // 3
rows.first().title; // "a"
rows.last().title; // "c"
rows.ids().length; // 3
rows.pluck("title"); // ["a", "b", "c"]
rows.project(["n"]); // [{ n: 1 }, { n: 2 }, { n: 3 }]
rows.reduce((sum, r) => sum + r.n, 0); // 6
rows.setAll("seen", true); // 3
rows.incAll("n", 10); // 3
Notes.sort("n").pluck("n"); // [11, 12, 13]
Notes.eq("seen", true).count(); // 3
rows[0].title = "A";
rows[1].title = "B";
rows.saveAll(); // 2
Notes.sort("n").pluck("title"); // ["A", "B", "c"]
rows.deleteAll(); // 3
Notes.count(); // 0
find and a chain's all() answer an Array of rows with these extra methods:
These methods apply to unprojected document results. find(..., { select })
and projection, grouping or compound chains return plain rows; ids, pluck
and ordinary Array map return ordinary arrays. saveAll counts rows with
unsaved changes that were saved; it can surface the first row conflict while
still saving other current rows.
| Method | Answers |
|---|---|
first(), last() |
a row or undefined |
ids(), pluck(field), project([fields]) |
id strings, one field of each, plain objects |
toArray(), toJSON() |
a plain Array of rows, of documents |
reduce(fn, initial), sort(compare) |
as Array |
setAll(field, v), incAll(field, n) |
write each row at once; the count |
saveAll() |
save the rows with unsaved changes; the count |
deleteAll() |
delete every row's document; the count |
Rules
- Writes through rows and collections join
db.transaction: a rollback takes them back. - A row is a snapshot for the call that read it; do not keep rows in module state.