monsqlize 1.0.0 → 1.0.2
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/CHANGELOG.md +92 -2419
- package/README.md +630 -1070
- package/index.d.ts +252 -15
- package/lib/cache.js +8 -8
- package/lib/common/validation.js +64 -1
- package/lib/connect.js +3 -3
- package/lib/errors.js +10 -0
- package/lib/index.js +118 -9
- package/lib/infrastructure/ssh-tunnel-ssh2.js +211 -0
- package/lib/infrastructure/ssh-tunnel.js +40 -0
- package/lib/infrastructure/uri-parser.js +35 -0
- package/lib/lock/Lock.js +66 -0
- package/lib/lock/errors.js +27 -0
- package/lib/lock/index.js +12 -0
- package/lib/logger.js +1 -1
- package/lib/model/examples/test.js +4 -4
- package/lib/mongodb/common/accessor-helpers.js +17 -3
- package/lib/mongodb/connect.js +68 -13
- package/lib/mongodb/index.js +140 -7
- package/lib/mongodb/management/collection-ops.js +4 -4
- package/lib/mongodb/management/index-ops.js +18 -18
- package/lib/mongodb/management/validation-ops.js +3 -3
- package/lib/mongodb/queries/aggregate.js +14 -5
- package/lib/mongodb/queries/chain.js +52 -45
- package/lib/mongodb/queries/count.js +16 -6
- package/lib/mongodb/queries/distinct.js +15 -6
- package/lib/mongodb/queries/find-and-count.js +22 -13
- package/lib/mongodb/queries/find-by-ids.js +5 -5
- package/lib/mongodb/queries/find-one-by-id.js +1 -1
- package/lib/mongodb/queries/find-one.js +12 -3
- package/lib/mongodb/queries/find-page.js +12 -0
- package/lib/mongodb/queries/find.js +15 -6
- package/lib/mongodb/queries/index.js +1 -0
- package/lib/mongodb/queries/watch.js +537 -0
- package/lib/mongodb/writes/delete-many.js +20 -11
- package/lib/mongodb/writes/delete-one.js +18 -9
- package/lib/mongodb/writes/find-one-and-delete.js +19 -10
- package/lib/mongodb/writes/find-one-and-replace.js +36 -20
- package/lib/mongodb/writes/find-one-and-update.js +36 -20
- package/lib/mongodb/writes/increment-one.js +16 -7
- package/lib/mongodb/writes/index.js +13 -13
- package/lib/mongodb/writes/insert-batch.js +46 -37
- package/lib/mongodb/writes/insert-many.js +22 -13
- package/lib/mongodb/writes/insert-one.js +18 -9
- package/lib/mongodb/writes/replace-one.js +33 -17
- package/lib/mongodb/writes/result-handler.js +14 -14
- package/lib/mongodb/writes/update-many.js +34 -18
- package/lib/mongodb/writes/update-one.js +33 -17
- package/lib/mongodb/writes/upsert-one.js +25 -9
- package/lib/operators.js +1 -1
- package/lib/redis-cache-adapter.js +3 -3
- package/lib/slow-query-log/base-storage.js +69 -0
- package/lib/slow-query-log/batch-queue.js +96 -0
- package/lib/slow-query-log/config-manager.js +195 -0
- package/lib/slow-query-log/index.js +237 -0
- package/lib/slow-query-log/mongodb-storage.js +323 -0
- package/lib/slow-query-log/query-hash.js +38 -0
- package/lib/transaction/DistributedCacheLockManager.js +240 -5
- package/lib/transaction/Transaction.js +1 -1
- package/lib/utils/objectid-converter.js +566 -0
- package/package.json +11 -5
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
* 删除单个匹配的文档
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { createError, ErrorCodes } = require(
|
|
7
|
-
const CacheFactory = require(
|
|
8
|
-
const { isInTransaction, getTransactionFromSession } = require(
|
|
6
|
+
const { createError, ErrorCodes } = require('../../errors');
|
|
7
|
+
const CacheFactory = require('../../cache');
|
|
8
|
+
const { isInTransaction, getTransactionFromSession } = require('../common/transaction-aware');
|
|
9
|
+
const { convertObjectIdStrings } = require('../../utils/objectid-converter');
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* 创建 deleteOne 操作
|
|
@@ -61,28 +62,36 @@ function createDeleteOneOps(context) {
|
|
|
61
62
|
const startTime = Date.now();
|
|
62
63
|
|
|
63
64
|
// 1. 参数验证
|
|
64
|
-
if (!filter || typeof filter !==
|
|
65
|
+
if (!filter || typeof filter !== 'object' || Array.isArray(filter)) {
|
|
65
66
|
throw createError(
|
|
66
67
|
ErrorCodes.INVALID_ARGUMENT,
|
|
67
|
-
|
|
68
|
-
[{ field:
|
|
68
|
+
'filter 必须是对象类型',
|
|
69
|
+
[{ field: 'filter', type: 'object.required', message: 'filter 是必需参数且必须是对象' }]
|
|
69
70
|
);
|
|
70
71
|
}
|
|
71
72
|
|
|
73
|
+
// ✅ v1.3.0: 自动转换 ObjectId 字符串
|
|
74
|
+
const convertedFilter = convertObjectIdStrings(filter, 'filter', 0, new WeakSet(), {
|
|
75
|
+
logger: context.logger,
|
|
76
|
+
excludeFields: context.autoConvertConfig?.excludeFields,
|
|
77
|
+
customFieldPatterns: context.autoConvertConfig?.customFieldPatterns,
|
|
78
|
+
maxDepth: context.autoConvertConfig?.maxDepth
|
|
79
|
+
});
|
|
80
|
+
|
|
72
81
|
// 2. 构建操作上下文
|
|
73
|
-
const operation =
|
|
82
|
+
const operation = 'deleteOne';
|
|
74
83
|
const ns = `${databaseName}.${collectionName}`;
|
|
75
84
|
|
|
76
85
|
try {
|
|
77
86
|
// 3. 执行删除操作
|
|
78
|
-
const result = await nativeCollection.deleteOne(
|
|
87
|
+
const result = await nativeCollection.deleteOne(convertedFilter, options);
|
|
79
88
|
|
|
80
89
|
// 4. 自动失效缓存(如果有文档被删除)
|
|
81
90
|
if (cache && result.deletedCount > 0) {
|
|
82
91
|
try {
|
|
83
92
|
const ns = {
|
|
84
93
|
iid: instanceId,
|
|
85
|
-
type:
|
|
94
|
+
type: 'mongodb',
|
|
86
95
|
db: databaseName,
|
|
87
96
|
collection: collectionName
|
|
88
97
|
};
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* 原子地查找并删除单个文档
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { createError, ErrorCodes } = require(
|
|
7
|
-
const CacheFactory = require(
|
|
8
|
-
const { handleFindOneAndResult, wasDocumentModified } = require(
|
|
9
|
-
const { isInTransaction, getTransactionFromSession } = require(
|
|
6
|
+
const { createError, ErrorCodes } = require('../../errors');
|
|
7
|
+
const CacheFactory = require('../../cache');
|
|
8
|
+
const { handleFindOneAndResult, wasDocumentModified } = require('./result-handler');
|
|
9
|
+
const { isInTransaction, getTransactionFromSession } = require('../common/transaction-aware');
|
|
10
|
+
const { convertObjectIdStrings } = require('../../utils/objectid-converter');
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* 创建 findOneAndDelete 操作
|
|
@@ -78,23 +79,31 @@ function createFindOneAndDeleteOps(context) {
|
|
|
78
79
|
const startTime = Date.now();
|
|
79
80
|
|
|
80
81
|
// 1. 参数验证
|
|
81
|
-
if (!filter || typeof filter !==
|
|
82
|
+
if (!filter || typeof filter !== 'object' || Array.isArray(filter)) {
|
|
82
83
|
throw createError(
|
|
83
84
|
ErrorCodes.INVALID_ARGUMENT,
|
|
84
|
-
|
|
85
|
-
[{ field:
|
|
85
|
+
'filter 必须是对象类型',
|
|
86
|
+
[{ field: 'filter', type: 'object.required', message: 'filter 是必需参数且必须是对象' }]
|
|
86
87
|
);
|
|
87
88
|
}
|
|
88
89
|
|
|
90
|
+
// ✅ v1.3.0: 自动转换 ObjectId 字符串
|
|
91
|
+
const convertedFilter = convertObjectIdStrings(filter, 'filter', 0, new WeakSet(), {
|
|
92
|
+
logger: context.logger,
|
|
93
|
+
excludeFields: context.autoConvertConfig?.excludeFields,
|
|
94
|
+
customFieldPatterns: context.autoConvertConfig?.customFieldPatterns,
|
|
95
|
+
maxDepth: context.autoConvertConfig?.maxDepth
|
|
96
|
+
});
|
|
97
|
+
|
|
89
98
|
// 2. 构建操作上下文
|
|
90
|
-
const operation =
|
|
99
|
+
const operation = 'findOneAndDelete';
|
|
91
100
|
const ns = `${databaseName}.${collectionName}`;
|
|
92
101
|
|
|
93
102
|
try {
|
|
94
103
|
// 3. 执行查找并删除操作
|
|
95
104
|
// MongoDB 驱动 6.x: 默认返回文档,需要 includeResultMetadata=true 获取完整元数据
|
|
96
105
|
const driverOptions = { ...options, includeResultMetadata: true };
|
|
97
|
-
const result = await nativeCollection.findOneAndDelete(
|
|
106
|
+
const result = await nativeCollection.findOneAndDelete(convertedFilter, driverOptions);
|
|
98
107
|
|
|
99
108
|
// 4. 自动失效缓存(如果有文档被删除)
|
|
100
109
|
// 使用安全的修改判断函数
|
|
@@ -103,7 +112,7 @@ function createFindOneAndDeleteOps(context) {
|
|
|
103
112
|
try {
|
|
104
113
|
const ns = {
|
|
105
114
|
iid: instanceId,
|
|
106
|
-
type:
|
|
115
|
+
type: 'mongodb',
|
|
107
116
|
db: databaseName,
|
|
108
117
|
collection: collectionName
|
|
109
118
|
};
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* 原子地查找并替换单个文档
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { createError, ErrorCodes } = require(
|
|
7
|
-
const CacheFactory = require(
|
|
8
|
-
const { handleFindOneAndResult, wasDocumentModified } = require(
|
|
9
|
-
const { isInTransaction, getTransactionFromSession } = require(
|
|
6
|
+
const { createError, ErrorCodes } = require('../../errors');
|
|
7
|
+
const CacheFactory = require('../../cache');
|
|
8
|
+
const { handleFindOneAndResult, wasDocumentModified } = require('./result-handler');
|
|
9
|
+
const { isInTransaction, getTransactionFromSession } = require('../common/transaction-aware');
|
|
10
|
+
const { convertObjectIdStrings } = require('../../utils/objectid-converter');
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* 创建 findOneAndReplace 操作
|
|
@@ -75,41 +76,56 @@ function createFindOneAndReplaceOps(context) {
|
|
|
75
76
|
const startTime = Date.now();
|
|
76
77
|
|
|
77
78
|
// 1. 参数验证
|
|
78
|
-
if (!filter || typeof filter !==
|
|
79
|
+
if (!filter || typeof filter !== 'object' || Array.isArray(filter)) {
|
|
79
80
|
throw createError(
|
|
80
81
|
ErrorCodes.INVALID_ARGUMENT,
|
|
81
|
-
|
|
82
|
-
[{ field:
|
|
82
|
+
'filter 必须是对象类型',
|
|
83
|
+
[{ field: 'filter', type: 'object.required', message: 'filter 是必需参数且必须是对象' }]
|
|
83
84
|
);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
if (!replacement || typeof replacement !==
|
|
87
|
+
if (!replacement || typeof replacement !== 'object' || Array.isArray(replacement)) {
|
|
87
88
|
throw createError(
|
|
88
89
|
ErrorCodes.INVALID_ARGUMENT,
|
|
89
|
-
|
|
90
|
-
[{ field:
|
|
90
|
+
'replacement 必须是对象类型',
|
|
91
|
+
[{ field: 'replacement', type: 'object.required', message: 'replacement 是必需参数且必须是对象' }]
|
|
91
92
|
);
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
// 验证 replacement 不包含更新操作符
|
|
95
96
|
const replacementKeys = Object.keys(replacement);
|
|
96
|
-
if (replacementKeys.some(key => key.startsWith(
|
|
97
|
+
if (replacementKeys.some(key => key.startsWith('$'))) {
|
|
97
98
|
throw createError(
|
|
98
99
|
ErrorCodes.INVALID_ARGUMENT,
|
|
99
|
-
|
|
100
|
-
[{ field:
|
|
100
|
+
'replacement 不能包含更新操作符(如 $set, $inc 等)',
|
|
101
|
+
[{ field: 'replacement', type: 'object.invalid', message: 'findOneAndReplace 用于完整替换文档,请使用 findOneAndUpdate 进行部分更新' }]
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
// ✅ v1.3.0: 自动转换 ObjectId 字符串
|
|
106
|
+
const convertedFilter = convertObjectIdStrings(filter, 'filter', 0, new WeakSet(), {
|
|
107
|
+
logger: context.logger,
|
|
108
|
+
excludeFields: context.autoConvertConfig?.excludeFields,
|
|
109
|
+
customFieldPatterns: context.autoConvertConfig?.customFieldPatterns,
|
|
110
|
+
maxDepth: context.autoConvertConfig?.maxDepth
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const convertedReplacement = convertObjectIdStrings(replacement, 'document', 0, new WeakSet(), {
|
|
114
|
+
logger: context.logger,
|
|
115
|
+
excludeFields: context.autoConvertConfig?.excludeFields,
|
|
116
|
+
customFieldPatterns: context.autoConvertConfig?.customFieldPatterns,
|
|
117
|
+
maxDepth: context.autoConvertConfig?.maxDepth
|
|
118
|
+
});
|
|
119
|
+
|
|
104
120
|
// 2. 构建操作上下文
|
|
105
|
-
const operation =
|
|
121
|
+
const operation = 'findOneAndReplace';
|
|
106
122
|
const ns = `${databaseName}.${collectionName}`;
|
|
107
123
|
|
|
108
124
|
try {
|
|
109
125
|
// 3. 执行查找并替换操作
|
|
110
126
|
// MongoDB 驱动 6.x: 默认返回文档,需要 includeResultMetadata=true 获取完整元数据
|
|
111
127
|
const driverOptions = { ...options, includeResultMetadata: true };
|
|
112
|
-
const result = await nativeCollection.findOneAndReplace(
|
|
128
|
+
const result = await nativeCollection.findOneAndReplace(convertedFilter, convertedReplacement, driverOptions);
|
|
113
129
|
|
|
114
130
|
// 4. 自动失效缓存(如果有文档被修改)
|
|
115
131
|
// 使用安全的修改判断函数
|
|
@@ -118,7 +134,7 @@ function createFindOneAndReplaceOps(context) {
|
|
|
118
134
|
try {
|
|
119
135
|
const ns = {
|
|
120
136
|
iid: instanceId,
|
|
121
|
-
type:
|
|
137
|
+
type: 'mongodb',
|
|
122
138
|
db: databaseName,
|
|
123
139
|
collection: collectionName
|
|
124
140
|
};
|
|
@@ -166,7 +182,7 @@ function createFindOneAndReplaceOps(context) {
|
|
|
166
182
|
replacementKeys: Object.keys(replacement),
|
|
167
183
|
found: result && result.value !== null,
|
|
168
184
|
upserted: result?.lastErrorObject?.upserted ? true : false,
|
|
169
|
-
returnDocument: options.returnDocument ||
|
|
185
|
+
returnDocument: options.returnDocument || 'before',
|
|
170
186
|
comment: options.comment
|
|
171
187
|
});
|
|
172
188
|
} else {
|
|
@@ -175,7 +191,7 @@ function createFindOneAndReplaceOps(context) {
|
|
|
175
191
|
duration,
|
|
176
192
|
found: result && result.value !== null,
|
|
177
193
|
upserted: result?.lastErrorObject?.upserted ? true : false,
|
|
178
|
-
returnDocument: options.returnDocument ||
|
|
194
|
+
returnDocument: options.returnDocument || 'before'
|
|
179
195
|
});
|
|
180
196
|
}
|
|
181
197
|
|
|
@@ -199,8 +215,8 @@ function createFindOneAndReplaceOps(context) {
|
|
|
199
215
|
if (error.code === 11000) {
|
|
200
216
|
throw createError(
|
|
201
217
|
ErrorCodes.DUPLICATE_KEY,
|
|
202
|
-
|
|
203
|
-
[{ field:
|
|
218
|
+
'查找并替换失败:违反唯一性约束',
|
|
219
|
+
[{ field: '_id', message: error.message }],
|
|
204
220
|
error
|
|
205
221
|
);
|
|
206
222
|
}
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
* 原子地查找并更新单个文档
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { createError, ErrorCodes } = require(
|
|
7
|
-
const CacheFactory = require(
|
|
8
|
-
const { handleFindOneAndResult, wasDocumentModified } = require(
|
|
9
|
-
const { isInTransaction, getTransactionFromSession } = require(
|
|
6
|
+
const { createError, ErrorCodes } = require('../../errors');
|
|
7
|
+
const CacheFactory = require('../../cache');
|
|
8
|
+
const { handleFindOneAndResult, wasDocumentModified } = require('./result-handler');
|
|
9
|
+
const { isInTransaction, getTransactionFromSession } = require('../common/transaction-aware');
|
|
10
|
+
const { convertObjectIdStrings, convertUpdateDocument } = require('../../utils/objectid-converter');
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* 创建 findOneAndUpdate 操作
|
|
@@ -76,41 +77,56 @@ function createFindOneAndUpdateOps(context) {
|
|
|
76
77
|
const startTime = Date.now();
|
|
77
78
|
|
|
78
79
|
// 1. 参数验证
|
|
79
|
-
if (!filter || typeof filter !==
|
|
80
|
+
if (!filter || typeof filter !== 'object' || Array.isArray(filter)) {
|
|
80
81
|
throw createError(
|
|
81
82
|
ErrorCodes.INVALID_ARGUMENT,
|
|
82
|
-
|
|
83
|
-
[{ field:
|
|
83
|
+
'filter 必须是对象类型',
|
|
84
|
+
[{ field: 'filter', type: 'object.required', message: 'filter 是必需参数且必须是对象' }]
|
|
84
85
|
);
|
|
85
86
|
}
|
|
86
87
|
|
|
87
|
-
if (!update || typeof update !==
|
|
88
|
+
if (!update || typeof update !== 'object' || Array.isArray(update)) {
|
|
88
89
|
throw createError(
|
|
89
90
|
ErrorCodes.INVALID_ARGUMENT,
|
|
90
|
-
|
|
91
|
-
[{ field:
|
|
91
|
+
'update 必须是对象类型',
|
|
92
|
+
[{ field: 'update', type: 'object.required', message: 'update 是必需参数且必须是对象' }]
|
|
92
93
|
);
|
|
93
94
|
}
|
|
94
95
|
|
|
95
96
|
// 验证 update 包含更新操作符
|
|
96
97
|
const updateKeys = Object.keys(update);
|
|
97
|
-
if (updateKeys.length > 0 && !updateKeys.some(key => key.startsWith(
|
|
98
|
+
if (updateKeys.length > 0 && !updateKeys.some(key => key.startsWith('$'))) {
|
|
98
99
|
throw createError(
|
|
99
100
|
ErrorCodes.INVALID_ARGUMENT,
|
|
100
|
-
|
|
101
|
-
[{ field:
|
|
101
|
+
'update 必须使用更新操作符(如 $set, $inc 等)',
|
|
102
|
+
[{ field: 'update', type: 'object.invalid', message: '请使用 $set, $inc, $push 等更新操作符,或使用 findOneAndReplace 进行整体替换' }]
|
|
102
103
|
);
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
// ✅ v1.3.0: 自动转换 ObjectId 字符串
|
|
107
|
+
const convertedFilter = convertObjectIdStrings(filter, 'filter', 0, new WeakSet(), {
|
|
108
|
+
logger: context.logger,
|
|
109
|
+
excludeFields: context.autoConvertConfig?.excludeFields,
|
|
110
|
+
customFieldPatterns: context.autoConvertConfig?.customFieldPatterns,
|
|
111
|
+
maxDepth: context.autoConvertConfig?.maxDepth
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
const convertedUpdate = convertUpdateDocument(update, {
|
|
115
|
+
logger: context.logger,
|
|
116
|
+
excludeFields: context.autoConvertConfig?.excludeFields,
|
|
117
|
+
customFieldPatterns: context.autoConvertConfig?.customFieldPatterns,
|
|
118
|
+
maxDepth: context.autoConvertConfig?.maxDepth
|
|
119
|
+
});
|
|
120
|
+
|
|
105
121
|
// 2. 构建操作上下文
|
|
106
|
-
const operation =
|
|
122
|
+
const operation = 'findOneAndUpdate';
|
|
107
123
|
const ns = `${databaseName}.${collectionName}`;
|
|
108
124
|
|
|
109
125
|
try {
|
|
110
126
|
// 3. 执行查找并更新操作
|
|
111
127
|
// MongoDB 驱动 6.x: 默认返回文档,需要 includeResultMetadata=true 获取完整元数据
|
|
112
128
|
const driverOptions = { ...options, includeResultMetadata: true };
|
|
113
|
-
const result = await nativeCollection.findOneAndUpdate(
|
|
129
|
+
const result = await nativeCollection.findOneAndUpdate(convertedFilter, convertedUpdate, driverOptions);
|
|
114
130
|
|
|
115
131
|
// 4. 自动失效缓存(如果有文档被修改)
|
|
116
132
|
// 使用安全的修改判断函数
|
|
@@ -119,7 +135,7 @@ function createFindOneAndUpdateOps(context) {
|
|
|
119
135
|
try {
|
|
120
136
|
const ns = {
|
|
121
137
|
iid: instanceId,
|
|
122
|
-
type:
|
|
138
|
+
type: 'mongodb',
|
|
123
139
|
db: databaseName,
|
|
124
140
|
collection: collectionName
|
|
125
141
|
};
|
|
@@ -167,7 +183,7 @@ function createFindOneAndUpdateOps(context) {
|
|
|
167
183
|
updateKeys: Object.keys(update),
|
|
168
184
|
found: result && result.value !== null,
|
|
169
185
|
upserted: result?.lastErrorObject?.upserted ? true : false,
|
|
170
|
-
returnDocument: options.returnDocument ||
|
|
186
|
+
returnDocument: options.returnDocument || 'before',
|
|
171
187
|
comment: options.comment
|
|
172
188
|
});
|
|
173
189
|
} else {
|
|
@@ -176,7 +192,7 @@ function createFindOneAndUpdateOps(context) {
|
|
|
176
192
|
duration,
|
|
177
193
|
found: result && result.value !== null,
|
|
178
194
|
upserted: result?.lastErrorObject?.upserted ? true : false,
|
|
179
|
-
returnDocument: options.returnDocument ||
|
|
195
|
+
returnDocument: options.returnDocument || 'before'
|
|
180
196
|
});
|
|
181
197
|
}
|
|
182
198
|
|
|
@@ -200,8 +216,8 @@ function createFindOneAndUpdateOps(context) {
|
|
|
200
216
|
if (error.code === 11000) {
|
|
201
217
|
throw createError(
|
|
202
218
|
ErrorCodes.DUPLICATE_KEY,
|
|
203
|
-
|
|
204
|
-
[{ field:
|
|
219
|
+
'查找并更新失败:违反唯一性约束',
|
|
220
|
+
[{ field: '_id', message: error.message }],
|
|
205
221
|
error
|
|
206
222
|
);
|
|
207
223
|
}
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
const { ObjectId } = require('mongodb');
|
|
7
7
|
const { createError, ErrorCodes } = require('../../errors');
|
|
8
|
-
const { isInTransaction, getTransactionFromSession } = require(
|
|
9
|
-
const { handleFindOneAndResult, wasDocumentModified } = require(
|
|
8
|
+
const { isInTransaction, getTransactionFromSession } = require('../common/transaction-aware');
|
|
9
|
+
const { handleFindOneAndResult, wasDocumentModified } = require('./result-handler');
|
|
10
|
+
const { convertObjectIdStrings } = require('../../utils/objectid-converter');
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* 创建 incrementOne 操作
|
|
@@ -91,6 +92,14 @@ function createIncrementOneOps(context) {
|
|
|
91
92
|
);
|
|
92
93
|
}
|
|
93
94
|
|
|
95
|
+
// ✅ v1.3.0: 自动转换 ObjectId 字符串
|
|
96
|
+
const convertedFilter = convertObjectIdStrings(filter, 'filter', 0, new WeakSet(), {
|
|
97
|
+
logger: context.logger,
|
|
98
|
+
excludeFields: context.autoConvertConfig?.excludeFields,
|
|
99
|
+
customFieldPatterns: context.autoConvertConfig?.customFieldPatterns,
|
|
100
|
+
maxDepth: context.autoConvertConfig?.maxDepth
|
|
101
|
+
});
|
|
102
|
+
|
|
94
103
|
// 2. 构建 $inc 更新对象
|
|
95
104
|
let incUpdate;
|
|
96
105
|
|
|
@@ -138,7 +147,7 @@ function createIncrementOneOps(context) {
|
|
|
138
147
|
const projection = actualOptions.projection;
|
|
139
148
|
|
|
140
149
|
const updateOptions = {
|
|
141
|
-
returnDocument
|
|
150
|
+
returnDocument,
|
|
142
151
|
includeResultMetadata: true,
|
|
143
152
|
maxTimeMS
|
|
144
153
|
};
|
|
@@ -148,7 +157,7 @@ function createIncrementOneOps(context) {
|
|
|
148
157
|
// 4. 执行 findOneAndUpdate 操作
|
|
149
158
|
let result;
|
|
150
159
|
try {
|
|
151
|
-
result = await collection.findOneAndUpdate(
|
|
160
|
+
result = await collection.findOneAndUpdate(convertedFilter, incUpdate, updateOptions);
|
|
152
161
|
} catch (error) {
|
|
153
162
|
throw error;
|
|
154
163
|
}
|
|
@@ -201,13 +210,13 @@ function createIncrementOneOps(context) {
|
|
|
201
210
|
operation: 'incrementOne',
|
|
202
211
|
durationMs: duration,
|
|
203
212
|
iid: instanceId,
|
|
204
|
-
type
|
|
213
|
+
type,
|
|
205
214
|
db: effectiveDbName,
|
|
206
215
|
collection: collection.collectionName,
|
|
207
216
|
found: result.value !== null,
|
|
208
217
|
filter: mongoSlowLogShaper?.sanitize ? mongoSlowLogShaper.sanitize(filter) : filter,
|
|
209
218
|
update: mongoSlowLogShaper?.sanitize ? mongoSlowLogShaper.sanitize(incUpdate) : incUpdate,
|
|
210
|
-
comment
|
|
219
|
+
comment
|
|
211
220
|
};
|
|
212
221
|
logger?.warn?.('🐌 Slow query: incrementOne', meta);
|
|
213
222
|
emit?.('slow-query', meta);
|
|
@@ -219,7 +228,7 @@ function createIncrementOneOps(context) {
|
|
|
219
228
|
// 7. 日志记录
|
|
220
229
|
logger?.debug?.('[incrementOne] 操作完成', {
|
|
221
230
|
ns: `${effectiveDbName}.${collection.collectionName}`,
|
|
222
|
-
duration
|
|
231
|
+
duration,
|
|
223
232
|
found: result && result.value !== null,
|
|
224
233
|
modified: wasDocumentModified(result)
|
|
225
234
|
});
|
|
@@ -3,19 +3,19 @@
|
|
|
3
3
|
* 统一导出所有写操作的工厂函数
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { createInsertOneOps } = require(
|
|
7
|
-
const { createInsertManyOps } = require(
|
|
8
|
-
const { createInsertBatchOps } = require(
|
|
9
|
-
const { createUpdateOneOps } = require(
|
|
10
|
-
const { createUpdateManyOps } = require(
|
|
11
|
-
const { createReplaceOneOps } = require(
|
|
12
|
-
const { createUpsertOneOps } = require(
|
|
13
|
-
const { createIncrementOneOps } = require(
|
|
14
|
-
const { createFindOneAndUpdateOps } = require(
|
|
15
|
-
const { createFindOneAndReplaceOps } = require(
|
|
16
|
-
const { createDeleteOneOps } = require(
|
|
17
|
-
const { createDeleteManyOps } = require(
|
|
18
|
-
const { createFindOneAndDeleteOps } = require(
|
|
6
|
+
const { createInsertOneOps } = require('./insert-one');
|
|
7
|
+
const { createInsertManyOps } = require('./insert-many');
|
|
8
|
+
const { createInsertBatchOps } = require('./insert-batch');
|
|
9
|
+
const { createUpdateOneOps } = require('./update-one');
|
|
10
|
+
const { createUpdateManyOps } = require('./update-many');
|
|
11
|
+
const { createReplaceOneOps } = require('./replace-one');
|
|
12
|
+
const { createUpsertOneOps } = require('./upsert-one'); // upsertOne 便利方法
|
|
13
|
+
const { createIncrementOneOps } = require('./increment-one'); // 新增:incrementOne 便利方法
|
|
14
|
+
const { createFindOneAndUpdateOps } = require('./find-one-and-update');
|
|
15
|
+
const { createFindOneAndReplaceOps } = require('./find-one-and-replace');
|
|
16
|
+
const { createDeleteOneOps } = require('./delete-one');
|
|
17
|
+
const { createDeleteManyOps } = require('./delete-many');
|
|
18
|
+
const { createFindOneAndDeleteOps } = require('./find-one-and-delete');
|
|
19
19
|
|
|
20
20
|
module.exports = {
|
|
21
21
|
// Insert 操作
|