如何在事务处理过程中从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()
}
}
}

如果你仔细想想,如果你还没有添加User,你怎么能添加HistoryEntry?这不是你目前正在做的"历史"。我相信你在这里有两个选项-手动在用户new Schema({ _id: { type: Schema.ObjectId, auto: true }})上设置_id,然后在事务中生成它:var userId = ObjectId();,并用于用户和历史条目。

第二个选项,我认为在这种情况下语义更正确——你应该附加到保存后挂钩:

schema.post('save', function(doc) {
console.log('%s has been saved', doc._id);
});

因此,每当创建用户时,都会触发保存后挂钩来更新历史记录。

最近遇到了同样的问题,希望您已经解决了。我可以为未来的求职者补充这一点。

  1. 下面的create函数返回一个已创建文档的数组
const user = await User.create(
[{ ...data, password: hashedPassword }],
{ session }
);

因此,以user[0]._id的身份访问用户id

  1. 将会话也传递给HistoryEntry.create()
HistoryEntry.create([{...},{...}], {session})

注意:在这个用例中,我个人更喜欢@marek第二个选项来使用保存后挂钩。

相关内容

最新更新