SQL updates
collection.updateOne(filter, update, options) and updateMany run document selection and mutation inside SQLite. JavaScript supplies bound JSON literals and returns result metadata. No update operator calls a JavaScript SQLite function or iterates over persisted documents in JavaScript.
Update a document or matching array elements
upsert: true inserts when nothing matches. It seeds supported equality predicates from the filter, including dotted paths and $and, before applying the update. Conflicting equality paths fail. Replacement upserts retain an equality-filter _id and reject a conflicting replacement ID. See the database reference for result fields.
insertMany and updateMany are atomic across the Silt operation. MongoDB ordinary batches can retain earlier successful writes, so this is a deliberate compatibility difference.
Implemented operators
An existing _id must be preserved. Setting it to an equal value is allowed; $rename involving _id is rejected. Pipeline updates that omit _id implicitly restore its original value, as MongoDB does.
Subqueries bind intermediate values once. Array mutations use json_each and ordered JSON aggregation. Native SQL guards abort invalid per-document transformations; storage wraps multi-document updates in a transaction, so an error rolls back the operation.
Boundaries and costs
- Input and stored values use the project's JSON domain. BSON dates, ObjectId, decimal, binary, and nonfinite numbers are not supported. Consequently
$currentDateis unavailable. - Legacy query-bound positional
$is explicitly rejected; use$[]or filtered$[identifier]. - Different positional identifiers, or differently spelled numeric components, whose normalized update paths could overlap are explicitly rejected. This conservative check also rejects some disjoint-filter updates that MongoDB can execute. Identical selectors on different child fields are supported.
- MongoDB-specific error codes/messages are not reproduced. Some document-dependent validation errors surface as SQLite
malformed JSON; the operation still rolls back. - Compound
$push.$sortuses native pairwise ranking to preserve value-order semantics. It is quadratic in the updated array length; it is intended for modest arrays, not as an indexed collection-sort substitute. - Very large explicit array indices materialize the required null padding in SQLite and can be expensive. Large/deep statements remain subject to SQLite's compilation and nesting limits.
modifiedCountcounts final JSON changes. MongoDB reports1for a pipeline that removes_idand implicitly restores it even when the final document is identical; Silt reports0in that narrow case.- Full MongoDB update parity is not claimed. Options other than
upsertandarrayFilters, unspecified operators, and unsupported aggregation expressions fail explicitly.
Verification
node --test test/update.test.js runs focused public API tests for update values, path construction, arrays, modifiers, input errors, rollback, metadata and upsert.
MONGODB_URI=... node --test test/mongo-update.test.js runs the same supported cases and rejection cases against an isolated database on a real MongoDB server. It is skipped without an explicit URI. The measured reference run used MongoDB 8.0.29, not the 8.3 target. The suite checks final documents and update counts, with the explicit _id pipeline-count exception above. Nonfinite arithmetic rejection is tested locally because MongoDB's BSON domain permits infinities.
The fixtures are authored for this implementation and include semantics discovered through real MongoDB execution, such as the distinction between $pull: 1 and $pull: { $eq: 1 } on nested arrays, and $push treating a dollar-prefixed object as a literal when $each is absent.