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/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('selectById(id-dup)', await wo.selectById('id-dup'))
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('selectById(id-dup)', await wo.selectById('id-dup'))
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('selectById(id-new)', await wo.selectById('id-new'))
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
- // selectById(id-dup) { id: 'id-dup', name: 'dup-1' }
56
+ // selectByPk(id-dup) { id: 'id-dup', name: 'dup-1' }
57
57
  // insert existed id { n: 1, nInserted: 0, ok: 1 }
58
- // selectById(id-dup) { id: 'id-dup', name: 'dup-1' }
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
- // selectById(id-new) { id: 'id-new', f0: 0, f1: 1, f2: 2, f4: 4, f3: 3 }
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "w-orm-mongodb",
3
- "version": "1.1.38",
3
+ "version": "1.1.40",
4
4
  "main": "dist/w-orm-mongodb.umd.js",
5
5
  "dependencies": {
6
6
  "mongodb": "^7.5.0",
@@ -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
- * 由id查詢單筆數據,因由MongoDB查找且僅回傳單筆,不需如select提取全部符合數據再處理,故數據量大時效能較佳
321
+ * 由主鍵查詢單筆數據,因由MongoDB查找且僅回傳單筆,不需如select提取全部符合數據再處理,故數據量大時效能較佳
322
+ * 註: 本套件之主鍵欄位固定為id,尚未支援由呼叫端指定
278
323
  * 註: 本函數不得有副作用,故不建立唯一索引
279
324
  *
280
325
  * @memberOf WOrmMongodb
281
- * @param {String} id 輸入id字串
282
- * @returns {Promise} 回傳Promise,resolve回傳數據物件,若無此id或id無效則回傳null,reject回傳錯誤訊息
326
+ * @param {String} pk 輸入主鍵值字串,即數據之id
327
+ * @returns {Promise} 回傳Promise,resolve回傳數據物件,若無此主鍵或主鍵值無效則回傳null,reject回傳錯誤訊息
283
328
  */
284
- async function selectById(id) {
329
+ async function selectByPk(pk) {
285
330
  let isErr = false
286
331
 
287
332
  //check
288
- if (!isestr(id)) {
289
- //未給有效id視為查無數據, 判定基準與insert、save、del內對id之認定一致
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, function(v) {
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, function(v) {
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 },id未給時自動產生,u8a須為Uint8Array
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
- if (!isestr(v.id)) {
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,由id查詢單筆數據
913
- * 註: 查無數據或id無效時回傳null,判定基準與selectById一致
948
+ * 使用GridFS,由主鍵查詢單筆數據
949
+ * 註: 查無數據或主鍵值無效時回傳null,判定基準與selectByPk一致
950
+ * 註: 本套件之主鍵欄位固定為id,尚未支援由呼叫端指定
914
951
  * 本函數不得有副作用,故不建立唯一索引
915
952
  *
916
953
  * @memberOf WOrmMongodb
917
- * @param {String} id 輸入查詢id字串
918
- * @returns {Promise} 回傳Promise,resolve回傳數據物件{ id, u8a },若無此id或id無效則回傳null,reject回傳錯誤訊息
954
+ * @param {String} pk 輸入主鍵值字串,即數據之id
955
+ * @returns {Promise} 回傳Promise,resolve回傳數據物件{ id, u8a },若無此主鍵或主鍵值無效則回傳null,reject回傳錯誤訊息
919
956
  */
920
- async function selectByIdGfs(id) {
957
+ async function selectByPkGfs(pk) {
921
958
  let isErr = false
922
959
 
923
960
  //check
924
- if (!isestr(id)) {
925
- //未給有效id視為查無數據, 判定基準與selectById一致
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(id)
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.selectById = selectById
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.selectByIdGfs = selectByIdGfs
1285
+ ee.selectByPkGfs = selectByPkGfs
1249
1286
  ee.insertGfs = insertGfs
1250
1287
  ee.delGfs = delGfs
1251
1288
  ee.delAllGfs = delAllGfs