w-orm-lmdb 1.0.11 → 1.0.12

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.
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li></ul></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li><li data-type='method'><a href="WOrmLmdb.html#.selectById">selectById</a></li></ul></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -469,7 +469,7 @@
469
469
 
470
470
  <dt class="tag-source">Source:</dt>
471
471
  <dd class="tag-source"><ul class="dummy"><li>
472
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line416">line 416</a>
472
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line523">line 523</a>
473
473
  </li></ul></dd>
474
474
 
475
475
 
@@ -630,7 +630,7 @@
630
630
 
631
631
  <dt class="tag-source">Source:</dt>
632
632
  <dd class="tag-source"><ul class="dummy"><li>
633
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line531">line 531</a>
633
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line638">line 638</a>
634
634
  </li></ul></dd>
635
635
 
636
636
 
@@ -808,7 +808,7 @@
808
808
 
809
809
  <dt class="tag-source">Source:</dt>
810
810
  <dd class="tag-source"><ul class="dummy"><li>
811
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line186">line 186</a>
811
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line239">line 239</a>
812
812
  </li></ul></dd>
813
813
 
814
814
 
@@ -969,7 +969,7 @@
969
969
 
970
970
  <dt class="tag-source">Source:</dt>
971
971
  <dd class="tag-source"><ul class="dummy"><li>
972
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line289">line 289</a>
972
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line342">line 342</a>
973
973
  </li></ul></dd>
974
974
 
975
975
 
@@ -1256,7 +1256,7 @@
1256
1256
 
1257
1257
  <dt class="tag-source">Source:</dt>
1258
1258
  <dd class="tag-source"><ul class="dummy"><li>
1259
- <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line132">line 132</a>
1259
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line137">line 137</a>
1260
1260
  </li></ul></dd>
1261
1261
 
1262
1262
 
@@ -1414,6 +1414,164 @@
1414
1414
 
1415
1415
 
1416
1416
 
1417
+
1418
+
1419
+
1420
+
1421
+ <h4 class="name" id=".selectById"><span class="type-signature type-signature-async, static">(async, static) </span>selectById<span class="signature">(id)</span><span class="type-signature"> &rarr; {Promise}</span></h4>
1422
+
1423
+
1424
+
1425
+
1426
+
1427
+
1428
+ <dl class="details">
1429
+
1430
+ <dt class="tag-description">Description:</dt>
1431
+ <dd class="tag-description"><ul class="dummy"><li><p>由主鍵id查詢單筆數據,因直接由LMDB取值,不需如select提取全表數據再過濾,故數據量大時效能較佳</p></li></ul></dd>
1432
+
1433
+
1434
+
1435
+ <dt class="tag-source">Source:</dt>
1436
+ <dd class="tag-source"><ul class="dummy"><li>
1437
+ <a href="WOrmLmdb.mjs.html">WOrmLmdb.mjs</a>, <a href="WOrmLmdb.mjs.html#line191">line 191</a>
1438
+ </li></ul></dd>
1439
+
1440
+
1441
+
1442
+
1443
+
1444
+
1445
+
1446
+
1447
+
1448
+
1449
+
1450
+
1451
+
1452
+
1453
+
1454
+
1455
+
1456
+
1457
+
1458
+
1459
+
1460
+
1461
+
1462
+
1463
+
1464
+
1465
+
1466
+
1467
+
1468
+
1469
+
1470
+ </dl>
1471
+
1472
+
1473
+
1474
+
1475
+
1476
+
1477
+
1478
+
1479
+
1480
+
1481
+
1482
+
1483
+
1484
+ <h5 class="h5-parameters">Parameters:</h5>
1485
+
1486
+
1487
+ <table class="params">
1488
+ <thead>
1489
+ <tr>
1490
+
1491
+ <th>Name</th>
1492
+
1493
+
1494
+ <th>Type</th>
1495
+
1496
+
1497
+
1498
+
1499
+
1500
+ <th class="last">Description</th>
1501
+ </tr>
1502
+ </thead>
1503
+
1504
+ <tbody>
1505
+
1506
+
1507
+ <tr>
1508
+
1509
+ <td class="name"><code>id</code></td>
1510
+
1511
+
1512
+ <td class="type">
1513
+
1514
+
1515
+ <span class="param-type">String</span>
1516
+
1517
+
1518
+
1519
+
1520
+ </td>
1521
+
1522
+
1523
+
1524
+
1525
+
1526
+ <td class="description last"><p>輸入主鍵字串</p></td>
1527
+ </tr>
1528
+
1529
+
1530
+ </tbody>
1531
+ </table>
1532
+
1533
+
1534
+
1535
+
1536
+
1537
+
1538
+
1539
+
1540
+
1541
+
1542
+
1543
+
1544
+
1545
+
1546
+
1547
+
1548
+ <h5 class="h5-returns">Returns:</h5>
1549
+
1550
+
1551
+ <div class="param-desc">
1552
+ <p>回傳Promise,resolve回傳數據物件,若無此id則回傳null,reject回傳錯誤訊息</p>
1553
+ </div>
1554
+
1555
+
1556
+
1557
+ <dl class="param-type">
1558
+ <dt>
1559
+ Type
1560
+ </dt>
1561
+ <dd>
1562
+
1563
+ <span class="param-type">Promise</span>
1564
+
1565
+
1566
+
1567
+ </dd>
1568
+ </dl>
1569
+
1570
+
1571
+
1572
+
1573
+
1574
+
1417
1575
 
1418
1576
 
1419
1577
 
@@ -1433,7 +1591,7 @@
1433
1591
  <br class="clear">
1434
1592
 
1435
1593
  <footer>
1436
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 08 2026 14:28:51 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1594
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sun Aug 16 2026 16:58:57 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
1437
1595
  </footer>
1438
1596
 
1439
1597
  <script>prettyPrint();</script>
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li></ul></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li><li data-type='method'><a href="WOrmLmdb.html#.selectById">selectById</a></li></ul></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -129,13 +129,8 @@ function WOrmLmdb(opt = {}) {
129
129
  return cloneDeep(_cache) //與外部使用數據脫勾
130
130
  }
131
131
 
132
- //waitFun
133
- await waitFun(() => {
134
- if (client.status === 'closed') {
135
- console.log(`client.status[${client.status}], level is closed`)
136
- }
137
- return client.status === 'open'
138
- })
132
+ //waitOpen
133
+ await waitOpen()
139
134
  // console.log('client.status',client.status)
140
135
 
141
136
  //ltdt
@@ -152,6 +147,16 @@ function WOrmLmdb(opt = {}) {
152
147
  return ltdt
153
148
  }
154
149
 
150
+ //waitOpen, 等待client開啟, 因getRange與get於client關閉時會拋錯
151
+ let waitOpen = async () => {
152
+ await waitFun(() => {
153
+ if (client.status === 'closed') {
154
+ console.log(`client.status[${client.status}], level is closed`)
155
+ }
156
+ return client.status === 'open'
157
+ })
158
+ }
159
+
155
160
  //getValue
156
161
  let getValue = async (key) => {
157
162
  let value = null
@@ -223,6 +228,54 @@ function WOrmLmdb(opt = {}) {
223
228
  return res
224
229
  }
225
230
 
231
+ /**
232
+ * 由主鍵id查詢單筆數據,因直接由LMDB取值,不需如select提取全表數據再過濾,故數據量大時效能較佳
233
+ *
234
+ * @memberOf WOrmLmdb
235
+ * @param {String} id 輸入主鍵字串
236
+ * @returns {Promise} 回傳Promise,resolve回傳數據物件,若無此id則回傳null,reject回傳錯誤訊息
237
+ */
238
+ async function selectById(id) {
239
+ let isErr = false
240
+ let res = null
241
+
242
+ try {
243
+
244
+ //check
245
+ if (!isestr(id)) {
246
+ //未給有效id視為查無數據
247
+ return null
248
+ }
249
+
250
+ //waitOpen
251
+ await waitOpen()
252
+
253
+ //查找資料表內id
254
+ let v = await getValue(id) //不會有catch
255
+
256
+ //check, 判定基準與insert、save、del內對既有數據之認定一致
257
+ if (iseobj(v)) {
258
+ res = v
259
+ }
260
+ else {
261
+ //不存在id, 回傳null
262
+ res = null
263
+ }
264
+
265
+ }
266
+ catch (err) {
267
+ isErr = true
268
+ res = err
269
+ }
270
+
271
+ //check
272
+ if (isErr) {
273
+ return Promise.reject(res)
274
+ }
275
+
276
+ return res
277
+ }
278
+
226
279
  /**
227
280
  * 插入數據
228
281
  *
@@ -263,29 +316,29 @@ function WOrmLmdb(opt = {}) {
263
316
  })
264
317
 
265
318
  //each
319
+ //ifNoExists, 由LMDB於同一寫交易內原子完成[檢查v.id未存在]與[寫入], 併發時同一v.id僅有一次成功,
320
+ //同批含重複v.id時亦僅首筆成功, 故不逐筆await而一次送出, 由LMDB寫執行緒依序處理並合併為批次寫交易
321
+ //注意: 回調函數須為同步函數, 且client.put須於回調函數內直接呼叫,
322
+ //若將client.put置於await之後, 該寫入會逸出條件批次而變成無條件寫入, 並使回傳值與實際狀態不一致
266
323
  let nAll = size(data)
267
- let nPush = 0
268
- for (let v of data) {
324
+ let ltdone = await Promise.all(map(data, function(v) {
269
325
  // console.log(v)
326
+ return client.ifNoExists(v.id, () => {
327
+ client.put(v.id, v)
328
+ })
329
+ }))
270
330
 
271
- //查找資料表內v.id
272
- let vv = await getValue(v.id) //不會有catch
273
- // console.log('getValue',vv)
274
-
275
- //check
276
- if (!iseobj(vv)) {
277
- //未存在v.id
278
-
279
- //put
280
- await client.put(v.id, v)
281
-
331
+ //nPush
332
+ let nPush = 0
333
+ each(ltdone, function(done) {
334
+ if (done) {
335
+ //未存在v.id, 已寫入
282
336
  nPush++
283
337
  }
284
338
  else {
285
339
  //已存在v.id則不push
286
340
  }
287
-
288
- }
341
+ })
289
342
 
290
343
  //res
291
344
  res = {
@@ -370,33 +423,74 @@ function WOrmLmdb(opt = {}) {
370
423
  //rest
371
424
  let rest = null
372
425
 
373
- //查找資料表內v.id
374
- let vv = await getValue(v.id) //不會有catch
426
+ //快速路徑, 先不開寫交易直接預讀, 內容相同者本就不須寫入, 可省去開啟寫交易之成本
427
+ //預讀值縱使已被其他寫入者更動而過期亦不影響正確性, 因內容相同時本次save等價於無操作,
428
+ //無操作可視為於預讀當下即已完成, 其後他人之寫入結果與[本次save先執行再輪到他人]相同
429
+ let vp = await getValue(v.id) //不會有catch
430
+ if (iseobj(vp) &amp;&amp; isEqual(v, vp)) {
431
+ //內容相同不更新
432
+ return {
433
+ n: 0,
434
+ nModified: 0,
435
+ ok: 1,
436
+ }
437
+ }
375
438
 
376
- //existed
377
- let existed = iseobj(vv)
439
+ //existed, updated, inserted
440
+ let existed = false
441
+ let updated = false
442
+ let inserted = false
378
443
 
379
- //check
380
- if (existed) {
381
- //已存在v.id
382
- if (isEqual(v, vv)) {
383
- //內容相同不更新
444
+ //transaction, 由LMDB於同一寫交易內原子完成[查找v.id]與[合併寫入],
445
+ //併發時不會有兩方各自讀到同一舊值再各自寫入而導致遺失更新
446
+ //注意: 回調函數須為同步函數, client.get於寫交易內為同步取值, 不可使用await,
447
+ //若將client.get或client.put置於await之後, 該操作會逸出本交易而失去原子性
448
+ await client.transaction(() => {
449
+
450
+ //查找資料表內v.id
451
+ let vv = client.get(v.id)
452
+
453
+ //existed
454
+ existed = iseobj(vv)
455
+
456
+ //check
457
+ if (existed) {
458
+ //已存在v.id
459
+ if (isEqual(v, vv)) {
460
+ //內容相同不更新
461
+ }
462
+ else {
463
+ //內容不同須更新
464
+
465
+ //merge and put
466
+ client.put(v.id, merge(vv, v))
467
+
468
+ updated = true
469
+ }
384
470
  }
385
471
  else {
386
- //內容不同須更新
472
+ //內容不存在, 若autoInsert則須插入
473
+ if (autoInsert) {
387
474
 
388
- //merge and put
389
- await client.put(v.id, merge(vv, v))
475
+ //put
476
+ client.put(v.id, v)
390
477
 
391
- rest = { update: true }
478
+ inserted = true
479
+ }
392
480
  }
393
- }
394
- else {
395
- //內容不存在
396
- }
481
+
482
+ })
397
483
 
398
484
  //rest
399
- if (iseobj(rest)) {
485
+ if (inserted) {
486
+ //內容不存在而自動插入, 回傳形狀同insert
487
+ rest = {
488
+ n: 1,
489
+ nInserted: 1,
490
+ ok: 1,
491
+ }
492
+ }
493
+ else if (updated) {
400
494
  rest = {
401
495
  n: 1,
402
496
  nModified: 1,
@@ -404,20 +498,33 @@ function WOrmLmdb(opt = {}) {
404
498
  }
405
499
  }
406
500
  else {
501
+ //rest.n === 0:
502
+ // 內容相同不更新, 不須update
503
+ // 內容不存在且未開啟autoInsert
407
504
  rest = {
408
505
  n: 0,
409
506
  nModified: 0,
410
507
  ok: 1,
411
508
  }
412
509
  }
413
- //rest.n === 0:
414
- // 內容相同不更新, 不須update
415
- // 內容不存在, 若autoInsert則須insert
416
-
417
- //autoInsert
418
- if (autoInsert &amp;&amp; rest.n === 0 &amp;&amp; !existed) {
419
- // console.log('insert(v)', v)
420
- rest = await insert(v)
510
+
511
+ //emit, 原autoInsert係轉呼叫insert故會發出insert事件, 此處維持既有行為,
512
+ //須於交易外發出, 避免外部訂閱函數於寫交易內執行
513
+ if (inserted) {
514
+
515
+ //update, 不能保證插入多少, 一律重設快取
516
+ _cache = null
517
+
518
+ try {
519
+
520
+ //emit
521
+ ee.emit('change', 'insert', [v], rest)
522
+
523
+ }
524
+ catch (err) {
525
+ console.log(err)
526
+ }
527
+
421
528
  }
422
529
 
423
530
  return rest
@@ -691,6 +798,7 @@ function WOrmLmdb(opt = {}) {
691
798
 
692
799
  //save
693
800
  ee.select = select
801
+ ee.selectById = selectById
694
802
  ee.insert = insert
695
803
  ee.save = save
696
804
  ee.del = del
@@ -716,7 +824,7 @@ export default WOrmLmdb
716
824
  <br class="clear">
717
825
 
718
826
  <footer>
719
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 08 2026 14:28:51 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
827
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sun Aug 16 2026 16:58:57 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
720
828
  </footer>
721
829
 
722
830
  <script>prettyPrint();</script>
package/docs/index.html CHANGED
@@ -29,7 +29,7 @@
29
29
  <nav >
30
30
 
31
31
 
32
- <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li></ul></li></ul>
32
+ <h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmLmdb.html">WOrmLmdb</a><ul class='methods'><li data-type='method'><a href="WOrmLmdb.html#.del">del</a></li><li data-type='method'><a href="WOrmLmdb.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmLmdb.html#.insert">insert</a></li><li data-type='method'><a href="WOrmLmdb.html#.save">save</a></li><li data-type='method'><a href="WOrmLmdb.html#.select">select</a></li><li data-type='method'><a href="WOrmLmdb.html#.selectById">selectById</a></li></ul></li></ul>
33
33
 
34
34
  </nav>
35
35
 
@@ -71,7 +71,7 @@
71
71
  <br class="clear">
72
72
 
73
73
  <footer>
74
- Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Aug 08 2026 14:28:51 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
74
+ Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sun Aug 16 2026 16:58:57 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
75
75
  </footer>
76
76
 
77
77
  <script>prettyPrint();</script>
package/g-basic.mjs CHANGED
@@ -99,6 +99,14 @@ async function test() {
99
99
  let so = await wo.select({ id: 'id-rosemary' })
100
100
  console.log('select', so)
101
101
 
102
+ //selectById
103
+ let sb = await wo.selectById('id-rosemary')
104
+ console.log('selectById', sb)
105
+
106
+ //selectById by id not existed
107
+ let sbn = await wo.selectById('id-not-existed')
108
+ console.log('selectById by id not existed', sbn)
109
+
102
110
  //select by $and, $gt, $lt
103
111
  let spa = await wo.select({ '$and': [{ value: { '$gt': 123 } }, { value: { '$lt': 200 } }] })
104
112
  console.log('select by $and, $gt, $lt', spa)
@@ -159,6 +167,8 @@ test()
159
167
  // { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 }
160
168
  // ]
161
169
  // select [ { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 } ]
170
+ // selectById { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 }
171
+ // selectById by id not existed null
162
172
  // select by $and, $gt, $lt [ { id: 'id-rosemary', name: 'rosemary(modify)', value: 123.456 } ]
163
173
  // select by $or, $gte, $lte [
164
174
  // {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "w-orm-lmdb",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "main": "dist/w-orm-lmdb.umd.js",
5
5
  "dependencies": {
6
6
  "lmdb": "^3.5.6",