mongodb - 如何在事务期间从 MongoDB 创建操作中检索 id?
问题描述
我正在尝试使用 Apollo Server 和 Mongoose 创建审计跟踪。当用户最初注册时,我会在用户集合中创建一个文档,并在历史集合中为他们提供的每条数据(用户名、密码、电子邮件等)创建一个文档。对于每个历史收集文档,我都包含用户文档的 id 以创建关系。完美运行。
但是,当我在其中添加事务时(见下文),用户文档的 userId 以未定义的形式返回,因此我无法将其添加到历史条目文档中。我假设在整个事务完成之前不会创建文档的 ID?
有任何想法吗?
Mutation: {
register: async (_, { data }) => {
// Start a mongo session & transaction
const session = await mongoose.startSession()
session.startTransaction()
try {
// Hash password and create user
const hashedPassword = await bcrypt.hash(data.password, 12)
const user = await User.create(
[{ ...data, password: hashedPassword }],
{ session }
)
// Add history entries
HistoryEntry.create([
{
user: user.id,
action: 'registered'
},
{
user: user.id,
action: 'set',
object: 'profile',
instance: user.id,
property: 'firstName',
value: firstName
},
{
user: user.id,
action: 'set',
object: 'profile',
instance: user.id,
property: 'lastName',
value: lastName
},
{
user: user.id,
action: 'set',
object: 'profile',
instance: user.id,
property: 'password'
}
])
if (loginType === 'email') {
HistoryEntry.create({
user: user.id,
action: 'set',
object: 'profile',
instance: user.id,
property: 'email',
value: login
})
}
if (loginType === 'mobile') {
HistoryEntry.create({
user: user.id,
action: 'set',
object: 'profile',
instance: user.id,
property: 'mobile',
value: login
})
}
// commit the changes if everything was successful
await session.commitTransaction()
return {
ok: true,
user
}
} catch (err) {
// if anything fails above, rollback the changes in the transaction
await session.abortTransaction()
return formatErrors(err)
} finally {
// end the session
session.endSession()
}
}
}
解决方案
如果你想一想,如果你还没有添加用户,你怎么能添加一个 HistoryEntry 呢?这不是你目前正在做的“历史”。我相信您在这里有两个选项 - 手动在用户上设置 _id new Schema({ _id: { type: Schema.ObjectId, auto: true }})
,然后在事务中生成它:var userId = ObjectId();
并用于用户和历史条目。
我相信第二个选项在这种情况下在语义上更正确 - 你应该附加到post-save 钩子:
schema.post('save', function(doc) {
console.log('%s has been saved', doc._id);
});
因此,每当创建用户时,都会触发保存后挂钩以更新历史记录。
推荐阅读
- html - Google Script - 在自定义表单提交时获取 Google Drive 链接到工作表(文件上传字段)
- selenium-webdriver - 需要通过失败的测试离开绿色构建
- sql-server - SQL Server:我正在尝试添加基于另一列的列值的条件选择
- php - 尽管有数据集,但 Cake PHP 2.x 模型验证在字段上返回错误
- python - 无法运行或重新安装或更新 yfinance
- apache-flink - 在 Flink Stateful 功能模块中存储数据库或第三方连接
- windows - 在 Windows PowerShell 中使用文件打开 notepad++
- angular - 离子中的Jitsi?
- google-cloud-vision - Cloud Vision API 是否支持 TIFF 和 PDF 标签检测?
- python - 我们可以只在数据集的某些类别上训练模型吗