w-orm-lmdb 1.0.18 → 1.0.20
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/README.md +44 -2
- package/dist/w-orm-lmdb.umd.js +2 -2
- package/dist/w-orm-lmdb.umd.js.map +1 -1
- package/docs/WOrmLmdb.html +303 -12
- package/docs/WOrmLmdb.mjs.html +184 -15
- package/docs/index.html +2 -2
- package/g-basic.mjs +43 -1
- package/package.json +1 -1
- package/src/WOrmLmdb.mjs +182 -13
- package/test/unit-closed.test.mjs +108 -0
- package/test/unit-insertbulk.test.mjs +205 -0
- package/test/unit-returnlist.test.mjs +195 -0
- package/toolg/gDistRollup.mjs +1 -1
- package//350/263/207/346/226/231/345/272/253/345/207/275/346/225/270/345/233/236/345/202/263/345/256/232/347/276/251/350/250/210/347/256/227.md +228 -42
- package/dist/req-mingo.umd.js +0 -7
- package/dist/req-mingo.umd.js.map +0 -1
package/docs/WOrmLmdb.mjs.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><li data-type='method'><a href="WOrmLmdb.html#.selectByPk">selectByPk</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#.insertBulk">insertBulk</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#.selectByPk">selectByPk</a></li></ul></li></ul>
|
|
33
33
|
|
|
34
34
|
</nav>
|
|
35
35
|
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
|
|
46
46
|
<section>
|
|
47
47
|
<article>
|
|
48
|
-
<pre class="prettyprint source linenums"><code>import { open } from 'lmdb'
|
|
48
|
+
<pre class="prettyprint source linenums"><code>import { open, ABORT } from 'lmdb'
|
|
49
49
|
// import mingo from 'mingo' //mingo內未更新import寫法, 會導致ERR_UNSUPPORTED_DIR_IMPORT, 故須改用require引入使用
|
|
50
50
|
import mingo from './reqMingo.js'
|
|
51
51
|
import size from 'lodash-es/size.js'
|
|
@@ -75,13 +75,13 @@ import waitFun from 'wsemi/src/waitFun.mjs'
|
|
|
75
75
|
* 故不監聽亦能取得完整資訊,且監聽與否不改變任何操作之回傳值。
|
|
76
76
|
*
|
|
77
77
|
* change事件,參數為(mode, data, res),於資料實際異動成功後發出:
|
|
78
|
-
* mode為操作別字串,可為'insert'、'save'、'del'、'delAll';save內若逐筆走自動插入則該筆另發出mode為'insert'之事件。
|
|
78
|
+
* mode為操作別字串,可為'insert'、'insertBulk'、'save'、'del'、'delAll';save內若逐筆走自動插入則該筆另發出mode為'insert'之事件。
|
|
79
79
|
* data為本次操作之輸入數據,delAll固定為null。
|
|
80
80
|
* res為本次操作之回傳結果。
|
|
81
81
|
* 逐筆函數以整批為單位發出一次而不逐筆發出,select與selectByPk不發出本事件。
|
|
82
82
|
*
|
|
83
83
|
* error事件,參數為(mode, data, err),於操作發生錯誤時發出:
|
|
84
|
-
* mode為操作別字串,可為'select'、'selectByPk'、'insert'、'save'、'del'、'delAll'。
|
|
84
|
+
* mode為操作別字串,可為'select'、'selectByPk'、'insert'、'insertBulk'、'save'、'del'、'delAll'。
|
|
85
85
|
* data為本次操作之輸入數據,無輸入數據者為null。
|
|
86
86
|
* err為錯誤訊息字串,內容與正規管道所送出者一致。
|
|
87
87
|
* 整批性錯誤於reject之前發出;逐筆失敗於該筆結果定案後發出,每筆一次。
|
|
@@ -173,13 +173,25 @@ function WOrmLmdb(opt = {}) {
|
|
|
173
173
|
}
|
|
174
174
|
|
|
175
175
|
//waitOpen, 等待client開啟, 因getRange與get於client關閉時會拋錯
|
|
176
|
+
//closed為終態: LMDB env一旦關閉不會自行回到open, 續等必然逾時, 故直接拋出而非空轉至逾時
|
|
177
|
+
//各函數入口已有procClosed守門, 此處之終態判斷為縱深防禦, 攔[操作進行中被close]之競態
|
|
178
|
+
//等待參數收斂: 開啟中為毫秒級過渡, 50次x200ms=10秒已極寬裕, 不使非終態之等待拖至waitFun預設之200秒
|
|
176
179
|
let waitOpen = async () => {
|
|
180
|
+
if (client.status === 'closed') {
|
|
181
|
+
throw new Error('client is closed, instance can not be used after close()')
|
|
182
|
+
}
|
|
177
183
|
await waitFun(() => {
|
|
178
|
-
if (client.status === 'closed') {
|
|
179
|
-
console.log(`client.status[${client.status}], level is closed`)
|
|
180
|
-
}
|
|
181
184
|
return client.status === 'open'
|
|
182
|
-
})
|
|
185
|
+
}, { attemptNum: 50, timeInterval: 200 })
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
//procClosed, 各函數入口之終態守門: close()後再操作屬整批性錯誤, 立即reject令誤用當場可見
|
|
189
|
+
//不可靜默回正常空值(如null或未命中), 否則[已關閉]與[查無資料]同形,
|
|
190
|
+
//去重類呼叫端將把每筆判為未存在而fail-open, 整批重送下游昂貴動作
|
|
191
|
+
let procClosed = (mode, data) => {
|
|
192
|
+
let msg = `can not ${mode} by closed client, instance can not be used after close()`
|
|
193
|
+
emitError(mode, data, msg)
|
|
194
|
+
return Promise.reject(new Error(msg))
|
|
183
195
|
}
|
|
184
196
|
|
|
185
197
|
//emitChange, 資料實際異動成功後發出, 事件僅為附加通知不承擔回傳義務
|
|
@@ -259,6 +271,11 @@ function WOrmLmdb(opt = {}) {
|
|
|
259
271
|
* @returns {Promise} 回傳Promise,resolve回傳數據,reject回傳錯誤訊息
|
|
260
272
|
*/
|
|
261
273
|
async function select(find = {}) {
|
|
274
|
+
|
|
275
|
+
//check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
|
|
276
|
+
if (client.status === 'closed') {
|
|
277
|
+
return procClosed('select', null)
|
|
278
|
+
}
|
|
262
279
|
let isErr = false
|
|
263
280
|
let res = null
|
|
264
281
|
|
|
@@ -318,6 +335,11 @@ function WOrmLmdb(opt = {}) {
|
|
|
318
335
|
* @returns {Promise} 回傳Promise,resolve回傳數據物件,若無此主鍵則回傳null,reject回傳錯誤訊息
|
|
319
336
|
*/
|
|
320
337
|
async function selectByPk(pk) {
|
|
338
|
+
|
|
339
|
+
//check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
|
|
340
|
+
if (client.status === 'closed') {
|
|
341
|
+
return procClosed('selectByPk', null)
|
|
342
|
+
}
|
|
321
343
|
let isErr = false
|
|
322
344
|
let res = null
|
|
323
345
|
|
|
@@ -367,13 +389,30 @@ function WOrmLmdb(opt = {}) {
|
|
|
367
389
|
*
|
|
368
390
|
* @memberOf WOrmLmdb
|
|
369
391
|
* @param {Object|Array} data 輸入數據物件或陣列
|
|
370
|
-
* @
|
|
392
|
+
* @param {Object} [option={}] 輸入設定物件,預設為{}
|
|
393
|
+
* @param {Boolean} [option.returnList=false] 輸入是否改回傳逐筆結果布林值,預設false。給true時回傳與輸入等長保序之陣列,各筆為{n,nInserted,ok},nInserted為1即該筆為新增;聚合計數只回答有幾筆是新的,逐筆結果方能回答是哪幾筆,供下游僅對新資料執行昂貴動作。回傳形式由呼叫點靜態決定,共用之結果處理程式碼不可跨不同取值之呼叫點混用
|
|
394
|
+
* @returns {Promise} 回傳Promise,resolve依returnList回傳插入結果:預設回傳聚合物件{n,nInserted,ok},n為輸入筆數、nInserted為實際插入筆數;returnList為true時回傳逐筆陣列,各筆n恆為1(主鍵命中或經插入)、ok恆為1(insert之錯誤皆屬整批性而reject,不進逐筆);reject回傳錯誤訊息
|
|
371
395
|
*/
|
|
372
|
-
async function insert(data) {
|
|
396
|
+
async function insert(data, option = {}) {
|
|
397
|
+
|
|
398
|
+
//check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
|
|
399
|
+
if (client.status === 'closed') {
|
|
400
|
+
return procClosed('insert', data)
|
|
401
|
+
}
|
|
373
402
|
let isErr = false
|
|
374
403
|
|
|
404
|
+
//returnList
|
|
405
|
+
let returnList = get(option, 'returnList')
|
|
406
|
+
if (!isbol(returnList)) {
|
|
407
|
+
returnList = false
|
|
408
|
+
}
|
|
409
|
+
|
|
375
410
|
//check
|
|
376
411
|
if (!iseobj(data) && !isearr(data)) {
|
|
412
|
+
if (returnList) {
|
|
413
|
+
//輸入無效, 對齊save與del之T5規定回傳空陣列
|
|
414
|
+
return []
|
|
415
|
+
}
|
|
377
416
|
return {
|
|
378
417
|
n: 0,
|
|
379
418
|
nInserted: 0,
|
|
@@ -422,9 +461,122 @@ function WOrmLmdb(opt = {}) {
|
|
|
422
461
|
})
|
|
423
462
|
|
|
424
463
|
//res
|
|
464
|
+
if (returnList) {
|
|
465
|
+
//逐筆結果, 與輸入等長保序, 元素沿用逐筆結果之家族形狀(同save與del之元素)
|
|
466
|
+
//n恆為1(主鍵命中既有或經插入而產生), ok恆為1(insert之錯誤皆屬整批性而reject, 不進逐筆),
|
|
467
|
+
//資訊由nInserted承載, filter(v=>v.nInserted===1)之長度必等於聚合模式之nInserted
|
|
468
|
+
res = map(ltdone, function(done) {
|
|
469
|
+
return {
|
|
470
|
+
n: 1,
|
|
471
|
+
nInserted: done ? 1 : 0,
|
|
472
|
+
ok: 1,
|
|
473
|
+
}
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
res = {
|
|
478
|
+
n: nAll,
|
|
479
|
+
nInserted: nPush,
|
|
480
|
+
ok: 1,
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
}
|
|
485
|
+
catch (err) {
|
|
486
|
+
isErr = true
|
|
487
|
+
res = err
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
//update, 不能保證插入多少, 一律重設快取
|
|
491
|
+
_cache = null
|
|
492
|
+
|
|
493
|
+
//emit, 於change可能須使用select, 故須放在重設快取之後
|
|
494
|
+
if (!isErr) {
|
|
495
|
+
emitChange('insert', data, res)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
//check
|
|
499
|
+
if (isErr) {
|
|
500
|
+
|
|
501
|
+
//emit, 整批性錯誤須於reject之前發出
|
|
502
|
+
emitError('insert', data, res)
|
|
503
|
+
|
|
504
|
+
return Promise.reject(res)
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return res
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* 批次插入數據,全批視為一個單位,全部插入成功或一筆都不寫入
|
|
512
|
+
* 註: 本函數非insert之加速版,兩者衝突政策不同。insert於主鍵已存在時跳過該筆而整批ok為1,
|
|
513
|
+
* 本函數則整批reject且不寫入任何一筆;同批含重複主鍵者亦視為衝突。確無衝突時兩者結果相同
|
|
514
|
+
* 註: 於本套件不會較insert快,因insert本即以Promise.all一次送出全部條件寫入而非逐筆await,
|
|
515
|
+
* 提供本函數係為與其他w-orm系列套件維持同一組函數,令呼叫端得於各套件間替換而不須改寫呼叫
|
|
516
|
+
*
|
|
517
|
+
* @memberOf WOrmLmdb
|
|
518
|
+
* @param {Object|Array} data 輸入數據物件或陣列
|
|
519
|
+
* @returns {Promise} 回傳Promise,resolve回傳插入結果物件{n,nInserted,ok},n為輸入筆數、nInserted成功時恆等於n,任一筆主鍵已存在則reject回傳錯誤訊息
|
|
520
|
+
*/
|
|
521
|
+
async function insertBulk(data) {
|
|
522
|
+
|
|
523
|
+
//check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
|
|
524
|
+
if (client.status === 'closed') {
|
|
525
|
+
return procClosed('insertBulk', data)
|
|
526
|
+
}
|
|
527
|
+
let isErr = false
|
|
528
|
+
|
|
529
|
+
//check
|
|
530
|
+
if (!iseobj(data) && !isearr(data)) {
|
|
531
|
+
return {
|
|
532
|
+
n: 0,
|
|
533
|
+
nInserted: 0,
|
|
534
|
+
ok: 1,
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
//cloneDeep, 與外部數據脫勾
|
|
539
|
+
data = cloneDeep(data)
|
|
540
|
+
|
|
541
|
+
//res
|
|
542
|
+
let res = null
|
|
543
|
+
try {
|
|
544
|
+
|
|
545
|
+
//check
|
|
546
|
+
if (!isarr(data)) {
|
|
547
|
+
data = [data]
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
//check id
|
|
551
|
+
data = procPk(data, 'insertBulk')
|
|
552
|
+
|
|
553
|
+
//nAll
|
|
554
|
+
let nAll = size(data)
|
|
555
|
+
|
|
556
|
+
//childTransaction, 全有全無由交易回滾保證
|
|
557
|
+
//註: 非同步之client.transaction於中止時並不回滾, 實測其內之put仍會落盤, 故此處須用childTransaction
|
|
558
|
+
//註: 交易內之client.get讀得到同一交易稍早之put, 故同批含重複主鍵者亦會於此被偵測為衝突
|
|
559
|
+
//註: 存在與否採鍵層判定, 與insert之ifNoExists一致
|
|
560
|
+
let pkConflict = null
|
|
561
|
+
await client.childTransaction(() => {
|
|
562
|
+
for (let v of data) {
|
|
563
|
+
if (client.get(v.id) !== undefined) {
|
|
564
|
+
pkConflict = v.id
|
|
565
|
+
return ABORT
|
|
566
|
+
}
|
|
567
|
+
client.put(v.id, v)
|
|
568
|
+
}
|
|
569
|
+
})
|
|
570
|
+
|
|
571
|
+
//check, 衝突則整批視為失敗, 交易已回滾故無任何寫入
|
|
572
|
+
if (isestr(pkConflict)) {
|
|
573
|
+
throw new Error(`can not insertBulk by existed id[${pkConflict}]`)
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
//res, 未衝突則全數插入, 故nInserted恆等於n
|
|
425
577
|
res = {
|
|
426
578
|
n: nAll,
|
|
427
|
-
nInserted:
|
|
579
|
+
nInserted: nAll,
|
|
428
580
|
ok: 1,
|
|
429
581
|
}
|
|
430
582
|
|
|
@@ -439,14 +591,14 @@ function WOrmLmdb(opt = {}) {
|
|
|
439
591
|
|
|
440
592
|
//emit, 於change可能須使用select, 故須放在重設快取之後
|
|
441
593
|
if (!isErr) {
|
|
442
|
-
emitChange('
|
|
594
|
+
emitChange('insertBulk', data, res)
|
|
443
595
|
}
|
|
444
596
|
|
|
445
597
|
//check
|
|
446
598
|
if (isErr) {
|
|
447
599
|
|
|
448
600
|
//emit, 整批性錯誤須於reject之前發出
|
|
449
|
-
emitError('
|
|
601
|
+
emitError('insertBulk', data, res)
|
|
450
602
|
|
|
451
603
|
return Promise.reject(res)
|
|
452
604
|
}
|
|
@@ -464,6 +616,11 @@ function WOrmLmdb(opt = {}) {
|
|
|
464
616
|
* @returns {Promise} 回傳Promise,resolve回傳與輸入等長之儲存結果陣列,各筆為{n,nInserted,nModified,ok},n為主鍵命中筆數,單筆失敗者ok為0並附err,reject回傳錯誤訊息
|
|
465
617
|
*/
|
|
466
618
|
async function save(data, option = {}) {
|
|
619
|
+
|
|
620
|
+
//check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
|
|
621
|
+
if (client.status === 'closed') {
|
|
622
|
+
return procClosed('save', data)
|
|
623
|
+
}
|
|
467
624
|
let isErr = false
|
|
468
625
|
|
|
469
626
|
//check
|
|
@@ -665,6 +822,11 @@ function WOrmLmdb(opt = {}) {
|
|
|
665
822
|
* @returns {Promise} 回傳Promise,resolve回傳與輸入等長之刪除結果陣列,各筆為{n,nDeleted,ok},n為主鍵命中筆數,單筆失敗或未給有效id者ok為0並附err,reject回傳錯誤訊息
|
|
666
823
|
*/
|
|
667
824
|
async function del(data) {
|
|
825
|
+
|
|
826
|
+
//check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
|
|
827
|
+
if (client.status === 'closed') {
|
|
828
|
+
return procClosed('del', data)
|
|
829
|
+
}
|
|
668
830
|
let isErr = false
|
|
669
831
|
|
|
670
832
|
//check
|
|
@@ -796,6 +958,11 @@ function WOrmLmdb(opt = {}) {
|
|
|
796
958
|
* @returns {Promise} 回傳Promise,resolve回傳刪除結果物件{n,nDeleted,ok},n與nDeleted同為實際刪除筆數,reject回傳錯誤訊息
|
|
797
959
|
*/
|
|
798
960
|
async function delAll(find = {}) {
|
|
961
|
+
|
|
962
|
+
//check client, closed為終態, 於任何檢查與寫入之前先行攔下(T4: 實例已關閉屬整批性錯誤)
|
|
963
|
+
if (client.status === 'closed') {
|
|
964
|
+
return procClosed('delAll', null)
|
|
965
|
+
}
|
|
799
966
|
let isErr = false
|
|
800
967
|
|
|
801
968
|
//res
|
|
@@ -898,7 +1065,8 @@ function WOrmLmdb(opt = {}) {
|
|
|
898
1065
|
return res
|
|
899
1066
|
}
|
|
900
1067
|
|
|
901
|
-
//close, 關閉內部LMDB env並釋放檔案鎖, close後該實例即報廢, 須重新new WOrmLmdb
|
|
1068
|
+
//close, 關閉內部LMDB env並釋放檔案鎖, close後該實例即報廢, 須重新new WOrmLmdb,
|
|
1069
|
+
//再呼叫任何操作函數將立即reject(訊息明示closed), 不與[查無資料]同形
|
|
902
1070
|
let close = async () => {
|
|
903
1071
|
if (client && client.status !== 'closed') {
|
|
904
1072
|
await client.close() //lmdb root database之close(), 回傳Promise
|
|
@@ -909,6 +1077,7 @@ function WOrmLmdb(opt = {}) {
|
|
|
909
1077
|
ee.select = select
|
|
910
1078
|
ee.selectByPk = selectByPk
|
|
911
1079
|
ee.insert = insert
|
|
1080
|
+
ee.insertBulk = insertBulk
|
|
912
1081
|
ee.save = save
|
|
913
1082
|
ee.del = del
|
|
914
1083
|
ee.delAll = delAll
|
|
@@ -933,7 +1102,7 @@ export default WOrmLmdb
|
|
|
933
1102
|
<br class="clear">
|
|
934
1103
|
|
|
935
1104
|
<footer>
|
|
936
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026
|
|
1105
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 17:58:14 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
937
1106
|
</footer>
|
|
938
1107
|
|
|
939
1108
|
<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><li data-type='method'><a href="WOrmLmdb.html#.selectByPk">selectByPk</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#.insertBulk">insertBulk</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#.selectByPk">selectByPk</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 Mon Aug 17 2026
|
|
74
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Mon Aug 17 2026 17:58:14 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
|
@@ -157,10 +157,44 @@ async function test() {
|
|
|
157
157
|
console.log('del by data without id catch', msg)
|
|
158
158
|
})
|
|
159
159
|
|
|
160
|
+
//insertBulk, 全批視為一個單位, 無衝突時nInserted恆等於n
|
|
161
|
+
await wo.insertBulk([{ id: 'id-bulk1', name: 'bulk1' }, { id: 'id-bulk2', name: 'bulk2' }])
|
|
162
|
+
.then(function(msg) {
|
|
163
|
+
console.log('insertBulk then', msg)
|
|
164
|
+
})
|
|
165
|
+
.catch(function(msg) {
|
|
166
|
+
console.log('insertBulk catch', msg)
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
//insertBulk by data with existed id, 非insert之加速版而係衝突政策不同
|
|
170
|
+
//insert於主鍵已存在時跳過該筆而整批ok為1, insertBulk則整批reject且不寫入任何一筆
|
|
171
|
+
await wo.insertBulk([{ id: 'id-bulk3', name: 'bulk3' }, { id: 'id-peter', name: 'conflict' }])
|
|
172
|
+
.then(function(msg) {
|
|
173
|
+
console.log('insertBulk by data with existed id then', msg)
|
|
174
|
+
})
|
|
175
|
+
.catch(function(msg) {
|
|
176
|
+
console.log('insertBulk by data with existed id catch', msg.toString())
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
//select all, 可見id-bulk3因整批reject而未寫入
|
|
180
|
+
let sb2 = await wo.select()
|
|
181
|
+
console.log('ids after insertBulk', _.map(_.sortBy(sb2, 'id'), 'id'))
|
|
182
|
+
|
|
183
|
+
//insert by returnList, 回傳與輸入等長保序之逐筆結果, nInserted為1即該筆為新增
|
|
184
|
+
//聚合計數只回答有幾筆是新的, 逐筆結果方能回答是哪幾筆, 供下游僅對新資料執行昂貴動作
|
|
185
|
+
let rl = await wo.insert([{ id: 'id-peter', name: 'dup' }, { id: 'id-new1', name: 'new1' }], { returnList: true })
|
|
186
|
+
console.log('insert by returnList', rl)
|
|
187
|
+
|
|
188
|
+
//filter, 以逐筆結果對位取出新增之數據
|
|
189
|
+
let fresh = [{ id: 'id-peter', name: 'dup' }, { id: 'id-new1', name: 'new1' }].filter(function(v, i) {
|
|
190
|
+
return rl[i].nInserted === 1
|
|
191
|
+
})
|
|
192
|
+
console.log('fresh by returnList', _.map(fresh, 'id'))
|
|
193
|
+
|
|
160
194
|
}
|
|
161
195
|
test()
|
|
162
196
|
// change delAll
|
|
163
|
-
// delAll then { n:
|
|
197
|
+
// delAll then { n: 5, nDeleted: 5, ok: 1 }
|
|
164
198
|
// change insert
|
|
165
199
|
// insert then { n: 3, nInserted: 3, ok: 1 }
|
|
166
200
|
// change save
|
|
@@ -208,6 +242,14 @@ test()
|
|
|
208
242
|
// error del can not delete by invalid id[]
|
|
209
243
|
// change del
|
|
210
244
|
// del by data without id then [ { n: 0, nDeleted: 0, ok: 0, err: 'can not delete by invalid id[]' } ]
|
|
245
|
+
// change insertBulk
|
|
246
|
+
// insertBulk then { n: 2, nInserted: 2, ok: 1 }
|
|
247
|
+
// error insertBulk can not insertBulk by existed id[id-peter]
|
|
248
|
+
// insertBulk by data with existed id catch Error: can not insertBulk by existed id[id-peter]
|
|
249
|
+
// ids after insertBulk [ 'id-bulk1', 'id-bulk2', 'id-peter', 'id-rosemary' ]
|
|
250
|
+
// change insert
|
|
251
|
+
// insert by returnList [ { n: 1, nInserted: 0, ok: 1 }, { n: 1, nInserted: 1, ok: 1 } ]
|
|
252
|
+
// fresh by returnList [ 'id-new1' ]
|
|
211
253
|
|
|
212
254
|
|
|
213
255
|
//node g-basic.mjs
|