w-orm-mongodb 1.1.38 → 1.1.40
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 +51 -47
- package/dist/w-orm-mongodb.umd.js +2 -2
- package/dist/w-orm-mongodb.umd.js.map +1 -1
- package/docs/WOrmMongodb.html +77 -29
- package/docs/WOrmMongodb.mjs.html +75 -38
- package/docs/index.html +2 -2
- package/g-basic.mjs +8 -8
- package/g-gfs.mjs +12 -12
- package/g-unique.mjs +6 -6
- package/package.json +1 -1
- package/src/WOrmMongodb.mjs +73 -36
- package/test/api-basic.test.mjs +258 -30
- package/test/api-gfs.test.mjs +146 -14
package/g-unique.mjs
CHANGED
|
@@ -28,12 +28,12 @@ async function test() {
|
|
|
28
28
|
{ id: 'id-uniq', name: 'uniq' },
|
|
29
29
|
])
|
|
30
30
|
console.log('insert with duplicated id', ri)
|
|
31
|
-
console.log('
|
|
31
|
+
console.log('selectByPk(id-dup)', await wo.selectByPk('id-dup'))
|
|
32
32
|
|
|
33
33
|
//insert, 對已存在id再插入則跳過而不覆寫
|
|
34
34
|
let re = await wo.insert({ id: 'id-dup', name: 'dup-3' })
|
|
35
35
|
console.log('insert existed id', re)
|
|
36
|
-
console.log('
|
|
36
|
+
console.log('selectByPk(id-dup)', await wo.selectByPk('id-dup'))
|
|
37
37
|
|
|
38
38
|
//insert, 併發對同一id插入10次, nInserted總和為1
|
|
39
39
|
let rc = await Promise.all(Array.from({ length: 10 }, (v, k) => {
|
|
@@ -48,19 +48,19 @@ async function test() {
|
|
|
48
48
|
}))
|
|
49
49
|
console.log('count of nInserted===1 by 5 concurrent save', rs.filter((v) => v[0].nInserted === 1).length)
|
|
50
50
|
console.log('records of id-new', (await wo.select({ id: 'id-new' })).length)
|
|
51
|
-
console.log('
|
|
51
|
+
console.log('selectByPk(id-new)', await wo.selectByPk('id-new'))
|
|
52
52
|
|
|
53
53
|
}
|
|
54
54
|
test()
|
|
55
55
|
// insert with duplicated id { n: 3, nInserted: 2, ok: 1 }
|
|
56
|
-
//
|
|
56
|
+
// selectByPk(id-dup) { id: 'id-dup', name: 'dup-1' }
|
|
57
57
|
// insert existed id { n: 1, nInserted: 0, ok: 1 }
|
|
58
|
-
//
|
|
58
|
+
// selectByPk(id-dup) { id: 'id-dup', name: 'dup-1' }
|
|
59
59
|
// sum of nInserted by 10 concurrent insert 1
|
|
60
60
|
// records of id-race 1
|
|
61
61
|
// count of nInserted===1 by 5 concurrent save 1
|
|
62
62
|
// records of id-new 1
|
|
63
|
-
//
|
|
63
|
+
// selectByPk(id-new) { id: 'id-new', f0: 0, f1: 1, f2: 2, f4: 4, f3: 3 }
|
|
64
64
|
// 註: 併發儲存之各欄位皆會保留, 惟欄位順序取決於各次儲存之完成順序, 故每次執行不盡相同
|
|
65
65
|
|
|
66
66
|
//node g-unique.mjs
|
package/package.json
CHANGED
package/src/WOrmMongodb.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import omit from 'lodash-es/omit.js'
|
|
|
9
9
|
import size from 'lodash-es/size.js'
|
|
10
10
|
import genPm from 'wsemi/src/genPm.mjs'
|
|
11
11
|
import genID from 'wsemi/src/genID.mjs'
|
|
12
|
+
import isbol from 'wsemi/src/isbol.mjs'
|
|
12
13
|
import isestr from 'wsemi/src/isestr.mjs'
|
|
13
14
|
import isarr from 'wsemi/src/isarr.mjs'
|
|
14
15
|
import isearr from 'wsemi/src/isearr.mjs'
|
|
@@ -20,11 +21,16 @@ import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
|
20
21
|
/**
|
|
21
22
|
* 操作資料庫(MongoDB)
|
|
22
23
|
*
|
|
24
|
+
* 本套件之主鍵欄位固定為id,尚未支援由呼叫端指定。id為無業務語義之識別碼。
|
|
25
|
+
* opt.autoGenPk預設為true,insert、save與insertGfs於輸入未帶有效id時自動產生;del於任一設定下皆不補值。
|
|
26
|
+
* opt.autoGenPk為false時套件一律不產生id,未帶有效id者以reject拋出,且id之唯一性與格式皆由呼叫端自負。
|
|
27
|
+
*
|
|
23
28
|
* @class
|
|
24
29
|
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
25
30
|
* @param {String} [opt.url='mongodb://127.0.0.1:27017'] 輸入連接資料庫字串,預設'mongodb://127.0.0.1:27017'
|
|
26
31
|
* @param {String} [opt.db='worm'] 輸入使用資料庫名稱字串,預設'worm'
|
|
27
32
|
* @param {String} [opt.cl='test'] 輸入使用資料表名稱字串,預設'test'
|
|
33
|
+
* @param {Boolean} [opt.autoGenPk=true] 輸入是否於輸入未帶有效主鍵時自動產生主鍵值,預設true。為false時主鍵須由呼叫端自備,屬依賴注入之定位,主鍵之唯一性、格式與是否與既有資料衝突皆由呼叫端自負。本設定為建構層設定,不得於insert與save之option逐次覆寫
|
|
28
34
|
* @returns {Object} 回傳操作資料庫物件,各事件功能詳見說明
|
|
29
35
|
*/
|
|
30
36
|
function WOrmMongodb(opt = {}) {
|
|
@@ -42,6 +48,13 @@ function WOrmMongodb(opt = {}) {
|
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
|
|
51
|
+
//autoGenPk, 預設開啟, 為false時主鍵一律由呼叫端自備, 套件不產生亦不補救
|
|
52
|
+
let autoGenPk = get(opt, 'autoGenPk')
|
|
53
|
+
if (!isbol(autoGenPk)) {
|
|
54
|
+
autoGenPk = true
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
45
58
|
//_indexReady, 唯一索引只須建立一次, 以旗標記錄避免每次操作皆多一次round-trip
|
|
46
59
|
let _indexReady = false
|
|
47
60
|
|
|
@@ -96,6 +109,37 @@ function WOrmMongodb(opt = {}) {
|
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
|
|
112
|
+
/**
|
|
113
|
+
* 檢查並補齊單筆數據之主鍵
|
|
114
|
+
* autoGenPk為true時未帶有效id者自動產生,為false時往外拋
|
|
115
|
+
* 註: 未帶有效id屬呼叫端未履行契約而非某一筆資料本身之問題,故為整批性錯誤而不降級為該筆ok為0,
|
|
116
|
+
* 若降級為逐筆結果,呼叫端易於整批resolve之下漏看,使[忘了給id]靜默變成[少寫了幾筆]
|
|
117
|
+
* 註: 本函數須於任何寫入之前一次對全部數據完成,令拋錯時同批之有效筆數亦不會被寫入
|
|
118
|
+
*
|
|
119
|
+
* @ignore
|
|
120
|
+
* @param {Object} v 輸入數據物件
|
|
121
|
+
* @param {Number} k 輸入數據於陣列內之索引
|
|
122
|
+
* @returns {Object} 回傳補齊主鍵之數據物件
|
|
123
|
+
*/
|
|
124
|
+
function procPk(v, k) {
|
|
125
|
+
|
|
126
|
+
//check
|
|
127
|
+
if (!isestr(v.id)) {
|
|
128
|
+
|
|
129
|
+
//check, autoGenPk為false時主鍵須由呼叫端自備
|
|
130
|
+
if (!autoGenPk) {
|
|
131
|
+
throw new Error(`invalid data[${k}].id, autoGenPk is false`)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//genID
|
|
135
|
+
v.id = genID()
|
|
136
|
+
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return v
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
99
143
|
/**
|
|
100
144
|
* 判定是否為唯一索引重複鍵錯誤(11000),批次插入時須全部寫入錯誤皆為重複鍵才算
|
|
101
145
|
*
|
|
@@ -274,19 +318,20 @@ function WOrmMongodb(opt = {}) {
|
|
|
274
318
|
|
|
275
319
|
|
|
276
320
|
/**
|
|
277
|
-
*
|
|
321
|
+
* 由主鍵查詢單筆數據,因由MongoDB查找且僅回傳單筆,不需如select提取全部符合數據再處理,故數據量大時效能較佳
|
|
322
|
+
* 註: 本套件之主鍵欄位固定為id,尚未支援由呼叫端指定
|
|
278
323
|
* 註: 本函數不得有副作用,故不建立唯一索引
|
|
279
324
|
*
|
|
280
325
|
* @memberOf WOrmMongodb
|
|
281
|
-
* @param {String}
|
|
282
|
-
* @returns {Promise} 回傳Promise,resolve
|
|
326
|
+
* @param {String} pk 輸入主鍵值字串,即數據之id
|
|
327
|
+
* @returns {Promise} 回傳Promise,resolve回傳數據物件,若無此主鍵或主鍵值無效則回傳null,reject回傳錯誤訊息
|
|
283
328
|
*/
|
|
284
|
-
async function
|
|
329
|
+
async function selectByPk(pk) {
|
|
285
330
|
let isErr = false
|
|
286
331
|
|
|
287
332
|
//check
|
|
288
|
-
if (!isestr(
|
|
289
|
-
|
|
333
|
+
if (!isestr(pk)) {
|
|
334
|
+
//未給有效主鍵值視為查無數據, 判定基準與insert、save、del內對id之認定一致
|
|
290
335
|
return null
|
|
291
336
|
}
|
|
292
337
|
|
|
@@ -302,7 +347,7 @@ function WOrmMongodb(opt = {}) {
|
|
|
302
347
|
let collection = database.collection(opt.cl)
|
|
303
348
|
|
|
304
349
|
//findOne, 以投影去除_id, 令回傳形狀與select一致
|
|
305
|
-
let v = await collection.findOne({ id }, { projection: { _id: 0 } })
|
|
350
|
+
let v = await collection.findOne({ id: pk }, { projection: { _id: 0 } })
|
|
306
351
|
|
|
307
352
|
//check, 判定基準與insert、save、del內對既有數據之認定一致
|
|
308
353
|
if (iseobj(v)) {
|
|
@@ -334,6 +379,7 @@ function WOrmMongodb(opt = {}) {
|
|
|
334
379
|
* 插入數據,僅於id不存在時寫入,已存在者跳過且不覆寫
|
|
335
380
|
* 由MongoDB於唯一索引上原子完成[檢查id未存在]與[寫入],併發時同一id僅有一次成功
|
|
336
381
|
* 註: n為輸入筆數,nInserted為實際插入筆數,全數已存在而nInserted為0屬正常結果
|
|
382
|
+
* 註: opt.autoGenPk為true(預設)時未帶有效id者自動產生,為false時未帶有效id即reject且同批皆不寫入
|
|
337
383
|
*
|
|
338
384
|
* @memberOf WOrmMongodb
|
|
339
385
|
* @param {Object|Array} data 輸入數據物件或陣列
|
|
@@ -373,13 +419,8 @@ function WOrmMongodb(opt = {}) {
|
|
|
373
419
|
data = [data]
|
|
374
420
|
}
|
|
375
421
|
|
|
376
|
-
//check id
|
|
377
|
-
data = map(data,
|
|
378
|
-
if (!isestr(v.id)) {
|
|
379
|
-
v.id = genID()
|
|
380
|
-
}
|
|
381
|
-
return v
|
|
382
|
-
})
|
|
422
|
+
//check id, 須於任何寫入之前一次完成, 令autoGenPk為false而拋錯時同批之有效筆數亦不會被寫入
|
|
423
|
+
data = map(data, procPk)
|
|
383
424
|
|
|
384
425
|
//ensureIndex
|
|
385
426
|
await ensureIndex(collection)
|
|
@@ -554,6 +595,7 @@ function WOrmMongodb(opt = {}) {
|
|
|
554
595
|
* 儲存數據,以id為準更新既有數據,未給之欄位會保留;id不存在且option.autoInsert為true時改為插入
|
|
555
596
|
* 註: n為id命中筆數,命中或經插入而產生皆為1;[內容相同]之判定基準為將待儲存物件合併進現值後結果與現值相同,
|
|
556
597
|
* 相同者不寫入而nModified為0;本筆失敗不中斷整批,該筆以ok為0並附err回報
|
|
598
|
+
* 註: opt.autoGenPk為true(預設)時未帶有效id者自動產生,為false時未帶有效id即reject且同批皆不寫入
|
|
557
599
|
*
|
|
558
600
|
* @memberOf WOrmMongodb
|
|
559
601
|
* @param {Object|Array} data 輸入數據物件或陣列
|
|
@@ -594,13 +636,8 @@ function WOrmMongodb(opt = {}) {
|
|
|
594
636
|
data = [data]
|
|
595
637
|
}
|
|
596
638
|
|
|
597
|
-
//check id
|
|
598
|
-
data = map(data,
|
|
599
|
-
if (!isestr(v.id)) {
|
|
600
|
-
v.id = genID()
|
|
601
|
-
}
|
|
602
|
-
return v
|
|
603
|
-
})
|
|
639
|
+
//check id, 須於任何寫入之前一次完成, 令autoGenPk為false而拋錯時同批之有效筆數亦不會被寫入
|
|
640
|
+
data = map(data, procPk)
|
|
604
641
|
|
|
605
642
|
//ensureIndex
|
|
606
643
|
await ensureIndex(collection)
|
|
@@ -804,8 +841,9 @@ function WOrmMongodb(opt = {}) {
|
|
|
804
841
|
|
|
805
842
|
/**
|
|
806
843
|
* 使用GridFS,插入數據,僅於id不存在時寫入,已存在者跳過且不覆寫
|
|
807
|
-
* 數據物件形狀為{ id, u8a },
|
|
844
|
+
* 數據物件形狀為{ id, u8a },u8a須為Uint8Array
|
|
808
845
|
* 註: n為輸入筆數,nInserted為實際插入筆數,全數已存在而nInserted為0屬正常結果
|
|
846
|
+
* 註: opt.autoGenPk為true(預設)時未帶有效id者自動產生,為false時未帶有效id即reject且同批皆不寫入
|
|
809
847
|
*
|
|
810
848
|
* @memberOf WOrmMongodb
|
|
811
849
|
* @param {Object|Array} data 輸入數據物件或陣列,各數據物件形狀為{ id, u8a }
|
|
@@ -855,9 +893,7 @@ function WOrmMongodb(opt = {}) {
|
|
|
855
893
|
//u8a無效屬呼叫端給值錯誤且整批函數無從逐筆回報, 故往外拋
|
|
856
894
|
data = map(data, function(v, k) {
|
|
857
895
|
v = { ...v }
|
|
858
|
-
|
|
859
|
-
v.id = genID()
|
|
860
|
-
}
|
|
896
|
+
v = procPk(v, k)
|
|
861
897
|
if (!isu8arr(v.u8a)) {
|
|
862
898
|
throw new Error(`invalid data[${k}].u8a`)
|
|
863
899
|
}
|
|
@@ -909,20 +945,21 @@ function WOrmMongodb(opt = {}) {
|
|
|
909
945
|
|
|
910
946
|
|
|
911
947
|
/**
|
|
912
|
-
* 使用GridFS
|
|
913
|
-
* 註:
|
|
948
|
+
* 使用GridFS,由主鍵查詢單筆數據
|
|
949
|
+
* 註: 查無數據或主鍵值無效時回傳null,判定基準與selectByPk一致
|
|
950
|
+
* 註: 本套件之主鍵欄位固定為id,尚未支援由呼叫端指定
|
|
914
951
|
* 本函數不得有副作用,故不建立唯一索引
|
|
915
952
|
*
|
|
916
953
|
* @memberOf WOrmMongodb
|
|
917
|
-
* @param {String}
|
|
918
|
-
* @returns {Promise} 回傳Promise,resolve回傳數據物件{ id, u8a }
|
|
954
|
+
* @param {String} pk 輸入主鍵值字串,即數據之id
|
|
955
|
+
* @returns {Promise} 回傳Promise,resolve回傳數據物件{ id, u8a },若無此主鍵或主鍵值無效則回傳null,reject回傳錯誤訊息
|
|
919
956
|
*/
|
|
920
|
-
async function
|
|
957
|
+
async function selectByPkGfs(pk) {
|
|
921
958
|
let isErr = false
|
|
922
959
|
|
|
923
960
|
//check
|
|
924
|
-
if (!isestr(
|
|
925
|
-
|
|
961
|
+
if (!isestr(pk)) {
|
|
962
|
+
//未給有效主鍵值視為查無數據, 判定基準與selectByPk一致
|
|
926
963
|
return null
|
|
927
964
|
}
|
|
928
965
|
|
|
@@ -979,11 +1016,11 @@ function WOrmMongodb(opt = {}) {
|
|
|
979
1016
|
try {
|
|
980
1017
|
|
|
981
1018
|
//core
|
|
982
|
-
let u8a = await core(
|
|
1019
|
+
let u8a = await core(pk)
|
|
983
1020
|
|
|
984
1021
|
//res, 形狀與insertGfs所收之數據物件一致
|
|
985
1022
|
res = {
|
|
986
|
-
id,
|
|
1023
|
+
id: pk,
|
|
987
1024
|
u8a,
|
|
988
1025
|
}
|
|
989
1026
|
|
|
@@ -1240,12 +1277,12 @@ function WOrmMongodb(opt = {}) {
|
|
|
1240
1277
|
|
|
1241
1278
|
//bind
|
|
1242
1279
|
ee.select = select
|
|
1243
|
-
ee.
|
|
1280
|
+
ee.selectByPk = selectByPk
|
|
1244
1281
|
ee.insert = insert
|
|
1245
1282
|
ee.save = save
|
|
1246
1283
|
ee.del = del
|
|
1247
1284
|
ee.delAll = delAll
|
|
1248
|
-
ee.
|
|
1285
|
+
ee.selectByPkGfs = selectByPkGfs
|
|
1249
1286
|
ee.insertGfs = insertGfs
|
|
1250
1287
|
ee.delGfs = delGfs
|
|
1251
1288
|
ee.delAllGfs = delAllGfs
|