w-orm-lowdb 1.0.30 → 1.0.32
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 +29 -1
- package/dist/w-orm-lowdb.umd.js +2 -2
- package/dist/w-orm-lowdb.umd.js.map +1 -1
- package/docs/WOrmLowdb.html +37 -15
- package/docs/WOrmLowdb.mjs.html +117 -22
- package/docs/index.html +1 -1
- package/g-basic.mjs +1 -1
- package/package.json +2 -2
- package/src/WOrmLowdb.mjs +116 -21
- package/test/unit-find-whitelist.test.mjs +533 -0
package/docs/WOrmLowdb.mjs.html
CHANGED
|
@@ -66,6 +66,7 @@ import isestr from 'wsemi/src/isestr.mjs'
|
|
|
66
66
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
67
67
|
import isearr from 'wsemi/src/isearr.mjs'
|
|
68
68
|
import haskey from 'wsemi/src/haskey.mjs'
|
|
69
|
+
import cvOrmFind from 'wsemi/src/cvOrmFind.mjs'
|
|
69
70
|
|
|
70
71
|
|
|
71
72
|
//kpGqueue, 以資料庫檔案路徑為鍵之全域序列化佇列, 詳見下方serialize說明
|
|
@@ -189,6 +190,64 @@ function WOrmLowdb(opt = {}) {
|
|
|
189
190
|
return pm
|
|
190
191
|
}
|
|
191
192
|
|
|
193
|
+
//isoFind, 把cvOrmFind所回傳複本內之Date就地轉為ISO字串(轉譯層): 數據以JSON存檔, Date於寫入時已成toISOString()之字串,
|
|
194
|
+
//條件內之Date不轉則恆不命中; 複本僅含null原型物件、密集陣列、純量與有效Date(無共享參照、無環), 就地轉換不影響呼叫端之find
|
|
195
|
+
let isoFind = (v) => {
|
|
196
|
+
if (v instanceof Date) {
|
|
197
|
+
return v.toISOString()
|
|
198
|
+
}
|
|
199
|
+
if (v !== null && typeof v === 'object') {
|
|
200
|
+
|
|
201
|
+
//物件與陣列皆以Object.keys走訪(陣列為密集, 鍵即索引)
|
|
202
|
+
for (let k of Object.keys(v)) {
|
|
203
|
+
v[k] = isoFind(v[k])
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return v
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
//hasProtoName, 檢核後複本之欄名是否同於Object.prototype之成員(constructor、toString、valueOf、hasOwnProperty等):
|
|
210
|
+
//此類欄名屬白名單內之合法欄名, 但mingo以屬性存取取值, 數據無此自有欄位時會取到繼承之成員(函數)而非缺欄,
|
|
211
|
+
//使{constructor:null}無命中、{constructor:{$ne:null}}命中全部(delAll因而刪光); 欄名只會出現於複本之鍵(含$and/$or內之子條件)
|
|
212
|
+
let hasProtoName = (fc) => {
|
|
213
|
+
for (let k of Object.keys(fc)) {
|
|
214
|
+
if (k === '$and' || k === '$or') {
|
|
215
|
+
for (let sub of fc[k]) {
|
|
216
|
+
if (hasProtoName(sub)) {
|
|
217
|
+
return true
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else if (k in Object.prototype) {
|
|
222
|
+
return true
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return false
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
//mkMatch, 依檢核後複本建立逐筆命中判定, select與delAll共用同一判定(系列最低要求①: select命中之數據即delAll刪除之數據);
|
|
229
|
+
//欄名同於Object.prototype成員者, 改以null原型之淺複本(只含自有可列舉欄位)判定, 令其與一般不存在之欄位同為缺欄語意, 命中者仍回傳原數據
|
|
230
|
+
let mkMatch = (fc) => {
|
|
231
|
+
let q = new Query(fc)
|
|
232
|
+
if (!hasProtoName(fc)) {
|
|
233
|
+
return (v) => q.test(v)
|
|
234
|
+
}
|
|
235
|
+
return (v) => q.test(v !== null && typeof v === 'object' ? Object.assign(Object.create(null), v) : v)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
//procFind, 條件之入口檢核(帳本R-FIND-01), 供select與delAll於serialize佇列之外、讀取之前呼叫:
|
|
239
|
+
//不合白名單者發出error事件(於reject之前)並回{err}, 由呼叫端reject, 不占用佇列; 合法者回{fc}為全新複本(null原型, 與呼叫端之find脫勾),
|
|
240
|
+
//其後一律只用此複本; 複本無自有鍵(未給、undefined、{})為全部
|
|
241
|
+
let procFind = (mode, find) => {
|
|
242
|
+
try {
|
|
243
|
+
return { fc: isoFind(cvOrmFind(find)) }
|
|
244
|
+
}
|
|
245
|
+
catch (err) {
|
|
246
|
+
emitError(mode, null, err)
|
|
247
|
+
return { err }
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
192
251
|
//emitChange, 資料實際異動成功後發出, 事件僅為附加通知不承擔回傳義務
|
|
193
252
|
//一律包try/catch, 令訂閱函數自身拋錯不影響本次操作之結果
|
|
194
253
|
let emitChange = (mode, data, res) => {
|
|
@@ -300,11 +359,15 @@ function WOrmLowdb(opt = {}) {
|
|
|
300
359
|
/**
|
|
301
360
|
* 查詢數據
|
|
302
361
|
*
|
|
362
|
+
* 條件find僅支援系列白名單(規則同delAll之第1-3點,見delAll),與delAll共用同一檢核,select(find)命中之數據即delAll(find)刪除之數據
|
|
363
|
+
*
|
|
303
364
|
* @memberOf WOrmLowdb
|
|
304
|
-
* @param {Object} [find={}] 輸入查詢條件物件
|
|
365
|
+
* @param {Object} [find={}] 輸入查詢條件物件(系列白名單,規則同delAll之第1-3點); 未給、undefined或{}回傳全部數據; 非條件物件或白名單外運算子整批reject
|
|
305
366
|
* @returns {Promise} 回傳Promise,resolve回傳數據陣列,無符合數據回傳空陣列,reject回傳錯誤訊息
|
|
306
367
|
*/
|
|
307
|
-
async function selectCore(find
|
|
368
|
+
async function selectCore(find) {
|
|
369
|
+
|
|
370
|
+
//find, 入口檢核後之複本(procFind), 不再讀取呼叫端之條件
|
|
308
371
|
let isErr = false
|
|
309
372
|
|
|
310
373
|
//res
|
|
@@ -314,15 +377,11 @@ function WOrmLowdb(opt = {}) {
|
|
|
314
377
|
//ltdt
|
|
315
378
|
let ltdt = await getData()
|
|
316
379
|
|
|
317
|
-
//filter
|
|
318
|
-
if (
|
|
319
|
-
|
|
320
|
-
//q
|
|
321
|
-
let q = new Query(find)
|
|
322
|
-
// console.log('q', q)
|
|
380
|
+
//filter, 複本無自有鍵(未給、undefined、{})為全部
|
|
381
|
+
if (Reflect.ownKeys(find).length > 0) {
|
|
323
382
|
|
|
324
|
-
//find
|
|
325
|
-
res =
|
|
383
|
+
//find, 與delAll共用同一逐筆判定
|
|
384
|
+
res = ltdt.filter(mkMatch(find))
|
|
326
385
|
// console.log('res', res)
|
|
327
386
|
|
|
328
387
|
}
|
|
@@ -354,7 +413,14 @@ function WOrmLowdb(opt = {}) {
|
|
|
354
413
|
return res
|
|
355
414
|
}
|
|
356
415
|
async function select(find = {}) {
|
|
357
|
-
|
|
416
|
+
|
|
417
|
+
//check find, 置於serialize佇列之外, 錯誤不占佇列(R-FIND-01)
|
|
418
|
+
let pf = procFind('select', find)
|
|
419
|
+
if (pf.err) {
|
|
420
|
+
return Promise.reject(pf.err)
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
return serialize(() => selectCore(pf.fc))
|
|
358
424
|
}
|
|
359
425
|
|
|
360
426
|
/**
|
|
@@ -1009,13 +1075,36 @@ function WOrmLowdb(opt = {}) {
|
|
|
1009
1075
|
}
|
|
1010
1076
|
|
|
1011
1077
|
/**
|
|
1012
|
-
*
|
|
1078
|
+
* 依條件刪除多筆數據(破壞性操作,須審慎使用,非必要不用;刪除單筆請用del)
|
|
1079
|
+
*
|
|
1080
|
+
* 使用須知:
|
|
1081
|
+
* 1. 不給條件即刪除全部數據: find未給、為undefined或為{}時,刪除資料表內全部數據,不另行確認。
|
|
1082
|
+
* 給了條件才是部分刪除。
|
|
1083
|
+
* 2. 傳了值卻不是條件物件(null、陣列含[]與[{...}]、字串、數值、布林、函數、Date、RegExp、Map、Set、類別實例等)
|
|
1084
|
+
* 一律整批reject,不視為{},不刪除任何數據。
|
|
1085
|
+
* 3. 條件僅支援系列白名單: 欄位等值{欄:純量}(多欄為AND)、欄位運算子$eq $ne $gt $gte $lt $lte(值為純量)與
|
|
1086
|
+
* $in $nin(值為純量陣列)、文件層$and $or(值為條件物件之非空陣列)。純量為字串(不含NUL字元與孤立代理字元)、有限數字、布林、有效Date;
|
|
1087
|
+
* null僅可用於欄位等值、$eq、$ne。白名單外之運算子($not $nor $regex $options $exists $where $expr $like $ilike等)、
|
|
1088
|
+
* 欄位層$and/$or、子查詢、函數值、Symbol鍵、undefined值、空的$nin/$and/$or等一律整批reject,
|
|
1089
|
+
* 訊息為invalid find: 原因 at [路徑],且不刪除任何數據。
|
|
1090
|
+
* 4. 與select共用同一檢核與同一條件,select(find)命中之數據即本函數刪除之數據;
|
|
1091
|
+
* 建議先以select(find)確認命中範圍再刪除(useCache開啟且他行程已寫入時,select可能回傳快取,而本函數一律直讀資料庫)。
|
|
1092
|
+
* 5. 條件值若來自可能為undefined、null或空陣列之變數,呼叫端須先自行判斷;undefined值會reject而非被忽略,
|
|
1093
|
+
* 空的$nin會reject,$in:[]則為恆假(刪除0筆)。
|
|
1094
|
+
* 6. 語意差異(依後端,見README): MongoDB式: $ne(比較值非null時)與$nin會命中欄位為null或缺欄之數據,$ne:null則排除之;
|
|
1095
|
+
* 欄名同於Object.prototype成員(constructor、toString等)者,數據無此自有欄位時視為缺欄;
|
|
1096
|
+
* Date條件於本後端轉為ISO字串後比較(與字串型欄位亦會比較,範圍比較僅在年份0000-9999內正確,見README)。
|
|
1097
|
+
* 需明確表達時可用可攜寫法: 排除NULL為{$and:[{f:{$ne:null}},{f:{$ne:x}}]},含NULL為{$or:[{f:null},{f:{$ne:x}}]}。
|
|
1098
|
+
*
|
|
1099
|
+
* n與nDeleted皆為實際刪除筆數,不取全表筆數。條件無命中時回{n:0,nDeleted:0,ok:1},不視為錯誤。
|
|
1013
1100
|
*
|
|
1014
1101
|
* @memberOf WOrmLowdb
|
|
1015
|
-
* @param {Object} [find={}]
|
|
1016
|
-
* @returns {Promise} 回傳Promise,resolve回傳刪除結果物件{n,nDeleted,ok},
|
|
1102
|
+
* @param {Object} [find={}] 輸入刪除條件物件,不給予find則代表刪除全部數據
|
|
1103
|
+
* @returns {Promise} 回傳Promise,resolve回傳刪除結果物件{n,nDeleted,ok},reject回傳錯誤訊息
|
|
1017
1104
|
*/
|
|
1018
|
-
async function delAllCore(find
|
|
1105
|
+
async function delAllCore(find) {
|
|
1106
|
+
|
|
1107
|
+
//find, 入口檢核後之複本(procFind), 不再讀取呼叫端之條件
|
|
1019
1108
|
let isErr = false
|
|
1020
1109
|
|
|
1021
1110
|
//res
|
|
@@ -1029,15 +1118,14 @@ function WOrmLowdb(opt = {}) {
|
|
|
1029
1118
|
let nAll = size(arrOld)
|
|
1030
1119
|
let nDel = 0
|
|
1031
1120
|
let arrNew = null
|
|
1032
|
-
if (
|
|
1121
|
+
if (Reflect.ownKeys(find).length > 0) {
|
|
1033
1122
|
|
|
1034
|
-
//
|
|
1035
|
-
let
|
|
1036
|
-
// console.log('q', q)
|
|
1123
|
+
//match, 與select共用同一逐筆判定
|
|
1124
|
+
let match = mkMatch(find)
|
|
1037
1125
|
|
|
1038
1126
|
//filter, 以與select同一條件逐筆判定, 保留未命中者
|
|
1039
1127
|
arrNew = filter(arrOld, (v) => {
|
|
1040
|
-
return !
|
|
1128
|
+
return !match(v)
|
|
1041
1129
|
})
|
|
1042
1130
|
|
|
1043
1131
|
//nDel
|
|
@@ -1094,7 +1182,14 @@ function WOrmLowdb(opt = {}) {
|
|
|
1094
1182
|
return res
|
|
1095
1183
|
}
|
|
1096
1184
|
async function delAll(find = {}) {
|
|
1097
|
-
|
|
1185
|
+
|
|
1186
|
+
//check find, 置於serialize佇列之外, 錯誤不占佇列(R-FIND-01)
|
|
1187
|
+
let pf = procFind('delAll', find)
|
|
1188
|
+
if (pf.err) {
|
|
1189
|
+
return Promise.reject(pf.err)
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
return serialize(() => delAllCore(pf.fc))
|
|
1098
1193
|
}
|
|
1099
1194
|
|
|
1100
1195
|
//bind
|
|
@@ -1125,7 +1220,7 @@ export default WOrmLowdb
|
|
|
1125
1220
|
<br class="clear">
|
|
1126
1221
|
|
|
1127
1222
|
<footer>
|
|
1128
|
-
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Oct
|
|
1223
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Oct 17 2026 14:56:45 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
1129
1224
|
</footer>
|
|
1130
1225
|
|
|
1131
1226
|
<script>prettyPrint();</script>
|
package/docs/index.html
CHANGED
|
@@ -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 Oct
|
|
74
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.5</a> on Sat Oct 17 2026 14:56:45 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
|
@@ -156,7 +156,7 @@ async function test() {
|
|
|
156
156
|
let spc = await wo.select({ '$or': [{ '$and': [{ value: { '$ne': 123 } }, { value: { '$in': [123, 321, 123.456, 456] } }, { value: { '$nin': [456, 654] } }] }, { '$or': [{ value: { '$lte': -1 } }, { value: { '$gte': 400 } }] }] })
|
|
157
157
|
console.log('select by $or, $and, $ne, $in, $nin', spc)
|
|
158
158
|
|
|
159
|
-
// //select by regex
|
|
159
|
+
// //select by regex //系列條件白名單不支援$regex(含$options), 會整批reject(invalid find: unsupported operator), 須改為select後自行過濾
|
|
160
160
|
// let sr = await wo.select({ name: { $regex: 'PeT', $options: '$i' } })
|
|
161
161
|
// console.log('selectReg', sr)
|
|
162
162
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "w-orm-lowdb",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.32",
|
|
4
4
|
"main": "dist/w-orm-lowdb.umd.js",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"lowdb": "^7.0.1",
|
|
7
7
|
"mingo": "^7.2.4",
|
|
8
|
-
"wsemi": "^1.9.
|
|
8
|
+
"wsemi": "^1.9.19"
|
|
9
9
|
},
|
|
10
10
|
"devDependencies": {
|
|
11
11
|
"w-package-tools": "^1.1.16"
|
package/src/WOrmLowdb.mjs
CHANGED
|
@@ -19,6 +19,7 @@ import isestr from 'wsemi/src/isestr.mjs'
|
|
|
19
19
|
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
20
20
|
import isearr from 'wsemi/src/isearr.mjs'
|
|
21
21
|
import haskey from 'wsemi/src/haskey.mjs'
|
|
22
|
+
import cvOrmFind from 'wsemi/src/cvOrmFind.mjs'
|
|
22
23
|
|
|
23
24
|
|
|
24
25
|
//kpGqueue, 以資料庫檔案路徑為鍵之全域序列化佇列, 詳見下方serialize說明
|
|
@@ -142,6 +143,64 @@ function WOrmLowdb(opt = {}) {
|
|
|
142
143
|
return pm
|
|
143
144
|
}
|
|
144
145
|
|
|
146
|
+
//isoFind, 把cvOrmFind所回傳複本內之Date就地轉為ISO字串(轉譯層): 數據以JSON存檔, Date於寫入時已成toISOString()之字串,
|
|
147
|
+
//條件內之Date不轉則恆不命中; 複本僅含null原型物件、密集陣列、純量與有效Date(無共享參照、無環), 就地轉換不影響呼叫端之find
|
|
148
|
+
let isoFind = (v) => {
|
|
149
|
+
if (v instanceof Date) {
|
|
150
|
+
return v.toISOString()
|
|
151
|
+
}
|
|
152
|
+
if (v !== null && typeof v === 'object') {
|
|
153
|
+
|
|
154
|
+
//物件與陣列皆以Object.keys走訪(陣列為密集, 鍵即索引)
|
|
155
|
+
for (let k of Object.keys(v)) {
|
|
156
|
+
v[k] = isoFind(v[k])
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return v
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
//hasProtoName, 檢核後複本之欄名是否同於Object.prototype之成員(constructor、toString、valueOf、hasOwnProperty等):
|
|
163
|
+
//此類欄名屬白名單內之合法欄名, 但mingo以屬性存取取值, 數據無此自有欄位時會取到繼承之成員(函數)而非缺欄,
|
|
164
|
+
//使{constructor:null}無命中、{constructor:{$ne:null}}命中全部(delAll因而刪光); 欄名只會出現於複本之鍵(含$and/$or內之子條件)
|
|
165
|
+
let hasProtoName = (fc) => {
|
|
166
|
+
for (let k of Object.keys(fc)) {
|
|
167
|
+
if (k === '$and' || k === '$or') {
|
|
168
|
+
for (let sub of fc[k]) {
|
|
169
|
+
if (hasProtoName(sub)) {
|
|
170
|
+
return true
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else if (k in Object.prototype) {
|
|
175
|
+
return true
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return false
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
//mkMatch, 依檢核後複本建立逐筆命中判定, select與delAll共用同一判定(系列最低要求①: select命中之數據即delAll刪除之數據);
|
|
182
|
+
//欄名同於Object.prototype成員者, 改以null原型之淺複本(只含自有可列舉欄位)判定, 令其與一般不存在之欄位同為缺欄語意, 命中者仍回傳原數據
|
|
183
|
+
let mkMatch = (fc) => {
|
|
184
|
+
let q = new Query(fc)
|
|
185
|
+
if (!hasProtoName(fc)) {
|
|
186
|
+
return (v) => q.test(v)
|
|
187
|
+
}
|
|
188
|
+
return (v) => q.test(v !== null && typeof v === 'object' ? Object.assign(Object.create(null), v) : v)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
//procFind, 條件之入口檢核(帳本R-FIND-01), 供select與delAll於serialize佇列之外、讀取之前呼叫:
|
|
192
|
+
//不合白名單者發出error事件(於reject之前)並回{err}, 由呼叫端reject, 不占用佇列; 合法者回{fc}為全新複本(null原型, 與呼叫端之find脫勾),
|
|
193
|
+
//其後一律只用此複本; 複本無自有鍵(未給、undefined、{})為全部
|
|
194
|
+
let procFind = (mode, find) => {
|
|
195
|
+
try {
|
|
196
|
+
return { fc: isoFind(cvOrmFind(find)) }
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
emitError(mode, null, err)
|
|
200
|
+
return { err }
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
145
204
|
//emitChange, 資料實際異動成功後發出, 事件僅為附加通知不承擔回傳義務
|
|
146
205
|
//一律包try/catch, 令訂閱函數自身拋錯不影響本次操作之結果
|
|
147
206
|
let emitChange = (mode, data, res) => {
|
|
@@ -253,11 +312,15 @@ function WOrmLowdb(opt = {}) {
|
|
|
253
312
|
/**
|
|
254
313
|
* 查詢數據
|
|
255
314
|
*
|
|
315
|
+
* 條件find僅支援系列白名單(規則同delAll之第1-3點,見delAll),與delAll共用同一檢核,select(find)命中之數據即delAll(find)刪除之數據
|
|
316
|
+
*
|
|
256
317
|
* @memberOf WOrmLowdb
|
|
257
|
-
* @param {Object} [find={}] 輸入查詢條件物件
|
|
318
|
+
* @param {Object} [find={}] 輸入查詢條件物件(系列白名單,規則同delAll之第1-3點); 未給、undefined或{}回傳全部數據; 非條件物件或白名單外運算子整批reject
|
|
258
319
|
* @returns {Promise} 回傳Promise,resolve回傳數據陣列,無符合數據回傳空陣列,reject回傳錯誤訊息
|
|
259
320
|
*/
|
|
260
|
-
async function selectCore(find
|
|
321
|
+
async function selectCore(find) {
|
|
322
|
+
|
|
323
|
+
//find, 入口檢核後之複本(procFind), 不再讀取呼叫端之條件
|
|
261
324
|
let isErr = false
|
|
262
325
|
|
|
263
326
|
//res
|
|
@@ -267,15 +330,11 @@ function WOrmLowdb(opt = {}) {
|
|
|
267
330
|
//ltdt
|
|
268
331
|
let ltdt = await getData()
|
|
269
332
|
|
|
270
|
-
//filter
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
//q
|
|
274
|
-
let q = new Query(find)
|
|
275
|
-
// console.log('q', q)
|
|
333
|
+
//filter, 複本無自有鍵(未給、undefined、{})為全部
|
|
334
|
+
if (Reflect.ownKeys(find).length > 0) {
|
|
276
335
|
|
|
277
|
-
//find
|
|
278
|
-
res =
|
|
336
|
+
//find, 與delAll共用同一逐筆判定
|
|
337
|
+
res = ltdt.filter(mkMatch(find))
|
|
279
338
|
// console.log('res', res)
|
|
280
339
|
|
|
281
340
|
}
|
|
@@ -307,7 +366,14 @@ function WOrmLowdb(opt = {}) {
|
|
|
307
366
|
return res
|
|
308
367
|
}
|
|
309
368
|
async function select(find = {}) {
|
|
310
|
-
|
|
369
|
+
|
|
370
|
+
//check find, 置於serialize佇列之外, 錯誤不占佇列(R-FIND-01)
|
|
371
|
+
let pf = procFind('select', find)
|
|
372
|
+
if (pf.err) {
|
|
373
|
+
return Promise.reject(pf.err)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return serialize(() => selectCore(pf.fc))
|
|
311
377
|
}
|
|
312
378
|
|
|
313
379
|
/**
|
|
@@ -962,13 +1028,36 @@ function WOrmLowdb(opt = {}) {
|
|
|
962
1028
|
}
|
|
963
1029
|
|
|
964
1030
|
/**
|
|
965
|
-
*
|
|
1031
|
+
* 依條件刪除多筆數據(破壞性操作,須審慎使用,非必要不用;刪除單筆請用del)
|
|
1032
|
+
*
|
|
1033
|
+
* 使用須知:
|
|
1034
|
+
* 1. 不給條件即刪除全部數據: find未給、為undefined或為{}時,刪除資料表內全部數據,不另行確認。
|
|
1035
|
+
* 給了條件才是部分刪除。
|
|
1036
|
+
* 2. 傳了值卻不是條件物件(null、陣列含[]與[{...}]、字串、數值、布林、函數、Date、RegExp、Map、Set、類別實例等)
|
|
1037
|
+
* 一律整批reject,不視為{},不刪除任何數據。
|
|
1038
|
+
* 3. 條件僅支援系列白名單: 欄位等值{欄:純量}(多欄為AND)、欄位運算子$eq $ne $gt $gte $lt $lte(值為純量)與
|
|
1039
|
+
* $in $nin(值為純量陣列)、文件層$and $or(值為條件物件之非空陣列)。純量為字串(不含NUL字元與孤立代理字元)、有限數字、布林、有效Date;
|
|
1040
|
+
* null僅可用於欄位等值、$eq、$ne。白名單外之運算子($not $nor $regex $options $exists $where $expr $like $ilike等)、
|
|
1041
|
+
* 欄位層$and/$or、子查詢、函數值、Symbol鍵、undefined值、空的$nin/$and/$or等一律整批reject,
|
|
1042
|
+
* 訊息為invalid find: 原因 at [路徑],且不刪除任何數據。
|
|
1043
|
+
* 4. 與select共用同一檢核與同一條件,select(find)命中之數據即本函數刪除之數據;
|
|
1044
|
+
* 建議先以select(find)確認命中範圍再刪除(useCache開啟且他行程已寫入時,select可能回傳快取,而本函數一律直讀資料庫)。
|
|
1045
|
+
* 5. 條件值若來自可能為undefined、null或空陣列之變數,呼叫端須先自行判斷;undefined值會reject而非被忽略,
|
|
1046
|
+
* 空的$nin會reject,$in:[]則為恆假(刪除0筆)。
|
|
1047
|
+
* 6. 語意差異(依後端,見README): MongoDB式: $ne(比較值非null時)與$nin會命中欄位為null或缺欄之數據,$ne:null則排除之;
|
|
1048
|
+
* 欄名同於Object.prototype成員(constructor、toString等)者,數據無此自有欄位時視為缺欄;
|
|
1049
|
+
* Date條件於本後端轉為ISO字串後比較(與字串型欄位亦會比較,範圍比較僅在年份0000-9999內正確,見README)。
|
|
1050
|
+
* 需明確表達時可用可攜寫法: 排除NULL為{$and:[{f:{$ne:null}},{f:{$ne:x}}]},含NULL為{$or:[{f:null},{f:{$ne:x}}]}。
|
|
1051
|
+
*
|
|
1052
|
+
* n與nDeleted皆為實際刪除筆數,不取全表筆數。條件無命中時回{n:0,nDeleted:0,ok:1},不視為錯誤。
|
|
966
1053
|
*
|
|
967
1054
|
* @memberOf WOrmLowdb
|
|
968
|
-
* @param {Object} [find={}]
|
|
969
|
-
* @returns {Promise} 回傳Promise,resolve回傳刪除結果物件{n,nDeleted,ok},
|
|
1055
|
+
* @param {Object} [find={}] 輸入刪除條件物件,不給予find則代表刪除全部數據
|
|
1056
|
+
* @returns {Promise} 回傳Promise,resolve回傳刪除結果物件{n,nDeleted,ok},reject回傳錯誤訊息
|
|
970
1057
|
*/
|
|
971
|
-
async function delAllCore(find
|
|
1058
|
+
async function delAllCore(find) {
|
|
1059
|
+
|
|
1060
|
+
//find, 入口檢核後之複本(procFind), 不再讀取呼叫端之條件
|
|
972
1061
|
let isErr = false
|
|
973
1062
|
|
|
974
1063
|
//res
|
|
@@ -982,15 +1071,14 @@ function WOrmLowdb(opt = {}) {
|
|
|
982
1071
|
let nAll = size(arrOld)
|
|
983
1072
|
let nDel = 0
|
|
984
1073
|
let arrNew = null
|
|
985
|
-
if (
|
|
1074
|
+
if (Reflect.ownKeys(find).length > 0) {
|
|
986
1075
|
|
|
987
|
-
//
|
|
988
|
-
let
|
|
989
|
-
// console.log('q', q)
|
|
1076
|
+
//match, 與select共用同一逐筆判定
|
|
1077
|
+
let match = mkMatch(find)
|
|
990
1078
|
|
|
991
1079
|
//filter, 以與select同一條件逐筆判定, 保留未命中者
|
|
992
1080
|
arrNew = filter(arrOld, (v) => {
|
|
993
|
-
return !
|
|
1081
|
+
return !match(v)
|
|
994
1082
|
})
|
|
995
1083
|
|
|
996
1084
|
//nDel
|
|
@@ -1047,7 +1135,14 @@ function WOrmLowdb(opt = {}) {
|
|
|
1047
1135
|
return res
|
|
1048
1136
|
}
|
|
1049
1137
|
async function delAll(find = {}) {
|
|
1050
|
-
|
|
1138
|
+
|
|
1139
|
+
//check find, 置於serialize佇列之外, 錯誤不占佇列(R-FIND-01)
|
|
1140
|
+
let pf = procFind('delAll', find)
|
|
1141
|
+
if (pf.err) {
|
|
1142
|
+
return Promise.reject(pf.err)
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
return serialize(() => delAllCore(pf.fc))
|
|
1051
1146
|
}
|
|
1052
1147
|
|
|
1053
1148
|
//bind
|