@lossless.org/nosqldb 10.5.0 → 10.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_rust/rustdb_linux_amd64 +0 -0
- package/dist_rust/rustdb_linux_amd64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_amd64_musl +0 -0
- package/dist_rust/rustdb_linux_amd64_musl.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_arm64 +0 -0
- package/dist_rust/rustdb_linux_arm64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_arm64_musl +0 -0
- package/dist_rust/rustdb_linux_arm64_musl.tsrust-build.json +5 -5
- package/dist_rust/rustdb_macos_amd64 +0 -0
- package/dist_rust/rustdb_macos_amd64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_macos_arm64 +0 -0
- package/dist_rust/rustdb_macos_arm64.tsrust-build.json +5 -5
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts_debugserver/bundled.js +3 -3
- package/package.json +6 -6
- package/readme.md +137 -14
- package/ts/00_commitinfo_data.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lossless.org/nosqldb",
|
|
3
|
-
"version": "10.
|
|
3
|
+
"version": "10.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A MongoDB-compatible embedded database server with wire protocol support, backed by a high-performance Rust engine.",
|
|
6
6
|
"exports": {
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@api.global/typedserver": "^8.4.6",
|
|
16
16
|
"@design.estate/dees-element": "^2.2.4",
|
|
17
|
-
"@git.zone/tsbuild": "^
|
|
18
|
-
"@git.zone/tsbundle": "^2.
|
|
19
|
-
"@git.zone/tsrust": "^1.
|
|
20
|
-
"@git.zone/tstest": "^6.
|
|
17
|
+
"@git.zone/tsbuild": "^5.0.0",
|
|
18
|
+
"@git.zone/tsbundle": "^2.15.0",
|
|
19
|
+
"@git.zone/tsrust": "^1.15.1",
|
|
20
|
+
"@git.zone/tstest": "^6.2.1",
|
|
21
21
|
"@lossless.org/client": "0.1.1",
|
|
22
|
-
"@types/node": "26.
|
|
22
|
+
"@types/node": "26.6.1",
|
|
23
23
|
"mongodb": "^7.5.0"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
package/readme.md
CHANGED
|
@@ -559,6 +559,17 @@ see the transaction snapshot plus its staged changes. Commit validates conflicts
|
|
|
559
559
|
and publishes atomically; abort discards staged changes. Write conflicts report
|
|
560
560
|
`WriteConflict` (112) with `TransientTransactionError`.
|
|
561
561
|
|
|
562
|
+
A staged write conflicts when it touches a document `_id` or a unique index key
|
|
563
|
+
that another transaction or statement wrote after this transaction's snapshot:
|
|
564
|
+
for example two transactions that both read a claim as absent and then insert
|
|
565
|
+
it under the same `_id`, or under distinct `_id`s with the same unique key.
|
|
566
|
+
Statements validate against the snapshot, so such a collision is reported when
|
|
567
|
+
the loser commits; nothing of the losing transaction is published. The driver's
|
|
568
|
+
`withTransaction` retries the transient error, and the retry observes the
|
|
569
|
+
winner. A key already visible in the transaction's snapshot is not a conflict:
|
|
570
|
+
inserting it fails the statement with `DuplicateKey` (11000), as outside a
|
|
571
|
+
transaction.
|
|
572
|
+
|
|
562
573
|
Commit/abort outcomes and successful retryable statement results survive file
|
|
563
574
|
storage restart. Duplicate commits replay their outcome; abort after commit
|
|
564
575
|
reports `TransactionCommitted` (256), commit after abort reports
|
|
@@ -1298,7 +1309,7 @@ await collection.findOneAndReplace({ _id: id }, { name: 'Replaced' }, { returnDo
|
|
|
1298
1309
|
|
|
1299
1310
|
// Element
|
|
1300
1311
|
{ email: { $exists: true } }
|
|
1301
|
-
{ type: { $type: 'string' } }
|
|
1312
|
+
{ type: { $type: 'string' } } { value: { $type: ['int', 'long'] } }
|
|
1302
1313
|
|
|
1303
1314
|
// Array
|
|
1304
1315
|
{ tags: { $all: ['mongodb', 'database'] } }
|
|
@@ -1307,8 +1318,28 @@ await collection.findOneAndReplace({ _id: id }, { name: 'Replaced' }, { returnDo
|
|
|
1307
1318
|
|
|
1308
1319
|
// Regex
|
|
1309
1320
|
{ name: { $regex: /^Al/i } }
|
|
1321
|
+
|
|
1322
|
+
// Aggregation expressions
|
|
1323
|
+
{ owner: 'o', $expr: { $lte: [{ $add: ['$retainedBytes', '$reservedBytes', size] }, max] } }
|
|
1324
|
+
{ $expr: { $gt: ['$leaseExpiresAt', '$$NOW'] } }
|
|
1310
1325
|
```
|
|
1311
1326
|
|
|
1327
|
+
`$type` takes a type alias (`'string'`, `'number'`, …), a numeric BSON type
|
|
1328
|
+
code or an array of them, and matches an array field through its elements as
|
|
1329
|
+
well as `'array'` itself.
|
|
1330
|
+
|
|
1331
|
+
`$expr` evaluates an aggregation expression per document in `find`, `count`,
|
|
1332
|
+
`distinct`, `update`, `delete`, `findAndModify` and a `$match` stage, and
|
|
1333
|
+
matches when the result is truthy. It accepts the operators listed under
|
|
1334
|
+
[Aggregation Pipeline](#aggregation-pipeline). Evaluation is charged against
|
|
1335
|
+
the same work budget as every other predicate, and an operator the engine does
|
|
1336
|
+
not implement is refused by name with `TypeMismatch` (code 14) before any
|
|
1337
|
+
document is read. `$$NOW` is one instant per command, as in MongoDB: the
|
|
1338
|
+
engine reads the clock once when the command starts, and the command's filter,
|
|
1339
|
+
every document of a pipeline update, every aggregation stage, `$lookup` and
|
|
1340
|
+
`$unionWith` sub-pipeline, and every `getMore` of its cursor see that instant.
|
|
1341
|
+
Filters outside a command, such as a partial index filter, have no `$$NOW`.
|
|
1342
|
+
|
|
1312
1343
|
### Update Operators
|
|
1313
1344
|
|
|
1314
1345
|
```typescript
|
|
@@ -1345,15 +1376,57 @@ const results = await collection.aggregate([
|
|
|
1345
1376
|
|
|
1346
1377
|
**Supported stages:** `$match`, `$project`, `$group`, `$sort`, `$limit`, `$skip`, `$unwind`, `$lookup`, `$addFields`, `$count`, `$facet`, `$replaceRoot`, `$set`, `$unionWith`, `$out`, `$merge`
|
|
1347
1378
|
|
|
1348
|
-
**Supported expression operators:**
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1379
|
+
**Supported expression operators:**
|
|
1380
|
+
|
|
1381
|
+
| Group | Operators |
|
|
1382
|
+
| --- | --- |
|
|
1383
|
+
| Comparison | `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$cmp` |
|
|
1384
|
+
| Arithmetic | `$add`, `$subtract`, `$multiply`, `$divide` |
|
|
1385
|
+
| Logical | `$and`, `$or`, `$not` |
|
|
1386
|
+
| Conditional and variables | `$cond` (array or `if`/`then`/`else` form), `$ifNull` (two or more operands), `$let` |
|
|
1387
|
+
| Type and arrays | `$isNumber`, `$type`, `$in`, `$size`, `$arrayElemAt` |
|
|
1388
|
+
| Dates | `$dateAdd` |
|
|
1389
|
+
| Collections | `$map`, `$objectToArray`, `$setEquals` |
|
|
1390
|
+
| Literals | `$literal` |
|
|
1391
|
+
|
|
1392
|
+
plus `$field` paths, `$$variable` references including `$$ROOT` and `$$NOW`,
|
|
1393
|
+
and documents or arrays of those. Every other operator is refused by name with
|
|
1394
|
+
`TypeMismatch` (code 14) before any document is read; the engine never treats
|
|
1395
|
+
an operator it cannot execute as a literal value.
|
|
1396
|
+
|
|
1397
|
+
Expressions follow MongoDB's value semantics. A field that is absent is
|
|
1398
|
+
*missing*, which is not `null`: `$type` answers `'missing'`, `$ifNull`
|
|
1399
|
+
replaces both, and comparisons order values as MongoDB does (MinKey, missing,
|
|
1400
|
+
`null`, numbers, strings, objects, arrays, binary data, ObjectIds, booleans,
|
|
1401
|
+
dates, timestamps, regular expressions, MaxKey), so `{ $eq: ['$absent', null] }`
|
|
1402
|
+
is false. Numbers compare by value across their wire types. A path through an
|
|
1403
|
+
array maps over its elements and always answers an array: `'$mailbox.path'`
|
|
1404
|
+
over one looked-up document is `['INBOX']`, so `$arrayElemAt` and `$size`
|
|
1405
|
+
apply to it. Arithmetic answers `null` when an operand is `null` or missing;
|
|
1406
|
+
an int result that overflows widens to a long and a long to a double, a double
|
|
1407
|
+
operand makes the result a double, and `$divide` always answers a double.
|
|
1408
|
+
`$add` accepts one date and answers a date; date minus date is milliseconds.
|
|
1409
|
+
Runtime errors keep MongoDB 7's codes: a non-numeric operand is
|
|
1410
|
+
`TypeMismatch` (14), `can't $divide by zero` is `BadValue` (2), a date that
|
|
1411
|
+
leaves the 64-bit range is `Overflow` (15), and the array and date operators
|
|
1412
|
+
answer MongoDB's location codes (a second date in `$add` 16612, `$in` without
|
|
1413
|
+
an array 40081, `$size` without an array 17124, `$arrayElemAt` 28689–28691,
|
|
1414
|
+
`$dateAdd` 5166403, 5166405, 5166406 and 5439013, a non-string time zone
|
|
1415
|
+
40517, an unknown unit `FailedToParse` (9)). Decimal128 operands in arithmetic
|
|
1416
|
+
are refused with `TypeMismatch` (14) — decimal arithmetic is not
|
|
1417
|
+
implemented. `$and`, `$or`, `$cond` and `$ifNull`
|
|
1418
|
+
evaluate, and charge, only the operands MongoDB evaluates, so a guard keeps an
|
|
1419
|
+
invalid branch from failing the statement. `$dateAdd` computes in UTC with the
|
|
1420
|
+
units `millisecond` to `year`, clamping `month`, `quarter` and `year` to the
|
|
1421
|
+
end of the target month; a `timezone` other than UTC is refused by name.
|
|
1422
|
+
Within a document expression a member that is missing is still written as
|
|
1423
|
+
`null`, where MongoDB omits the member.
|
|
1353
1424
|
|
|
1354
1425
|
`$lookup` supports the equality form and a bounded correlated pipeline form with
|
|
1355
|
-
`let`, an optional `$match`
|
|
1356
|
-
`$limit`.
|
|
1426
|
+
`let`, an optional `$match` (any filter, `$expr` included), and an optional
|
|
1427
|
+
following `$limit`. A `let` variable that reads an absent local field is bound
|
|
1428
|
+
to the missing value, as in MongoDB. Correlated string equality predicates
|
|
1429
|
+
(`$expr` with `$eq`, optionally under `$and`) can use a full-key or subset
|
|
1357
1430
|
foreign equality index to reduce candidates when available. Candidates are
|
|
1358
1431
|
paged, the complete expression remains authoritative, and `$limit` counts only
|
|
1359
1432
|
exact expression matches. Other BSON value shapes use the bounded scan path.
|
|
@@ -1368,6 +1441,18 @@ matcher cannot pre-compile fall back to the unnarrowed load, so results are
|
|
|
1368
1441
|
unchanged. The materialization limit therefore applies to the matched set, which
|
|
1369
1442
|
is what lets `countDocuments(filter)` run against collections larger than it.
|
|
1370
1443
|
|
|
1444
|
+
The scalar members of a `$in` or `$nin` list are looked up in a set built when
|
|
1445
|
+
the filter is validated, so a document costs the size of its value, not the
|
|
1446
|
+
length of the list: `countDocuments({ _id: { $in: ids } })` answers for tens of
|
|
1447
|
+
thousands of ids. Equality is unchanged: numbers of every type are equal by
|
|
1448
|
+
value (1, `NumberLong(1)`, 1.0 and `NumberDecimal("1.00")`), an array field
|
|
1449
|
+
matches through its elements or as a whole, and a missing field matches a list
|
|
1450
|
+
that holds `null`. Documents, arrays and regular expressions in a list are
|
|
1451
|
+
compared one by one and charged as such. A regular expression in a list is
|
|
1452
|
+
still compared as a value and not yet applied to strings, which differs from
|
|
1453
|
+
MongoDB, where it matches the strings it describes; that difference is a known
|
|
1454
|
+
open defect.
|
|
1455
|
+
|
|
1371
1456
|
**Group accumulators:** `$sum`, `$avg`, `$min`, `$max`, `$first`, `$last`, `$push`, `$addToSet`, `$count`
|
|
1372
1457
|
|
|
1373
1458
|
`$group._id` accepts a literal (`null`, a number, a string), a `$field`
|
|
@@ -1397,12 +1482,50 @@ await collection.dropIndexes(); // drop all except _id
|
|
|
1397
1482
|
> 🛡️ **Unique indexes are enforced at the engine level.** Duplicate values are rejected with a `DuplicateKey` error (code 11000) *before* the document is written to disk — on `insertOne`, `updateOne`, `findAndModify`, and upserts. Index definitions and entries are committed with native storage and survive restart.
|
|
1398
1483
|
|
|
1399
1484
|
NoSQLDB supports ascending and descending index keys with `name`, `unique`,
|
|
1400
|
-
`sparse`, and `expireAfterSeconds` options. It
|
|
1401
|
-
validated no-op and index version `v: 2`.
|
|
1402
|
-
|
|
1403
|
-
index in the request is created. Native maintenance expires eligible BSON
|
|
1404
|
-
and date arrays in bounded batches, preserving publication holds and
|
|
1405
|
-
snapshots.
|
|
1485
|
+
`sparse`, `partialFilterExpression` and `expireAfterSeconds` options. It
|
|
1486
|
+
accepts `background` as a validated no-op and index version `v: 2`.
|
|
1487
|
+
Unsupported options, including `collation` and `hidden`, are rejected before
|
|
1488
|
+
any index in the request is created. Native maintenance expires eligible BSON
|
|
1489
|
+
dates and date arrays in bounded batches, preserving publication holds and
|
|
1490
|
+
active snapshots.
|
|
1491
|
+
|
|
1492
|
+
**Partial indexes.** An index with a `partialFilterExpression` holds only the
|
|
1493
|
+
documents that match the filter, and a unique partial index enforces
|
|
1494
|
+
uniqueness among those documents only:
|
|
1495
|
+
|
|
1496
|
+
```typescript
|
|
1497
|
+
await jobs.createIndex(
|
|
1498
|
+
{ activeClaimKey: 1 },
|
|
1499
|
+
{ unique: true, partialFilterExpression: { activeClaimKey: { $exists: true } } },
|
|
1500
|
+
);
|
|
1501
|
+
await pulls.createIndex(
|
|
1502
|
+
{ org: 1, repo: 1, sourceRef: 1, targetRef: 1 },
|
|
1503
|
+
{ unique: true, partialFilterExpression: { state: 'open' } },
|
|
1504
|
+
);
|
|
1505
|
+
```
|
|
1506
|
+
|
|
1507
|
+
The filter accepts MongoDB's subset: equality (`field: value` or `$eq`),
|
|
1508
|
+
`$exists: true`, `$gt`, `$gte`, `$lt`, `$lte`, `$type`, `$in`, `$and` and
|
|
1509
|
+
`$or`, nested at most four expression levels deep. Any other expression —
|
|
1510
|
+
`$exists: false`, `$ne`, `$nin`, `$not`, `$nor`, regular expressions,
|
|
1511
|
+
`$elemMatch`, `$size`, `$expr`, and a regular expression inside `$in` — and a
|
|
1512
|
+
filter combined with `sparse` are refused with `CannotCreateIndex` (code 67);
|
|
1513
|
+
a malformed filter is `BadValue` (2) and a non-document is `TypeMismatch` (14).
|
|
1514
|
+
An update that moves a document into the filter claims its key, one that moves
|
|
1515
|
+
it out releases it, and transactions claim keys the same way, so a racing
|
|
1516
|
+
claim is a `WriteConflict` (112) with `TransientTransactionError`.
|
|
1517
|
+
`listIndexes`, canonical export and import report the filter exactly as it was
|
|
1518
|
+
created. The filter identifies the index: the same name with a different
|
|
1519
|
+
filter is `IndexKeySpecsConflict` (86); the same key with an equivalent filter
|
|
1520
|
+
under another name is `IndexOptionsConflict` (85); a different filter over the
|
|
1521
|
+
same key under another name is a separate index. Equivalence treats implicit
|
|
1522
|
+
equality and `$eq`, the order of conjuncts and `$or` branches, numeric wire
|
|
1523
|
+
types and `$in` duplicates as MongoDB's normalised expressions do. The query
|
|
1524
|
+
planner never selects a partial index on its own; a `hint` naming one reads
|
|
1525
|
+
only its members, as MongoDB's hinted scan does. A partial TTL index expires
|
|
1526
|
+
only its members. Engines older than this release refuse a storage root that
|
|
1527
|
+
holds a partial index instead of enforcing its uniqueness over every
|
|
1528
|
+
document.
|
|
1406
1529
|
|
|
1407
1530
|
`find()` and collection `aggregate()` accept `hint` as an index name (including
|
|
1408
1531
|
`_id_`) or an exact ascending/descending key pattern. Key-pattern order matters;
|
package/ts/00_commitinfo_data.ts
CHANGED