这是我的 Mongoose 架构,分别用于三个集合用户、帐户和交易:
const userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
lowercase: true,
minLength: 3,
maxLength: 30
},
password: {
type: String,
required: true,
minLength: 6
},
firstName: {
type: String,
required: true,
trim: true,
maxLength: 50
},
lastName: {
type: String,
required: true,
trim: true,
maxLength: 50
}
});
const accountSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User"
},
balance: {
type: Number,
minLength: 0,
required: true
}
})
const transactionSchema = new mongoose.Schema({
sender: {
_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
},
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
},
receiver: {
_id: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
},
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
}
},
amount: {
type: Number,
required: true
}
});
transactionSchema 的定义是这样的,希望 mongoose 能够理解,因为 _id 的 ref:“User”属性(不要在这个问题上评判我,chatGPT 是这样建议我的。而且,你可以评判我) ,自动填充发送者和接收者的名字和姓氏字段。
当前定义的 transactionsSchema 不允许发生以下转账逻辑:
accountRouter.post("/transfer", authMiddleware, async (req, res) => {
const session = await mongoose.startSession();
session.startTransaction();
const { amount, to } = req.body;
//...some logic that's not relevant to this question
//...
// Perform the transfer
await AccountModel.updateOne({ user: req.body.userId }, { $inc: { balance: -amount } }).session(session);
await AccountModel.updateOne({ user: to }, { $inc: { balance: amount } }).session(session);
await TransactionModel.create({ sender: {_id: req.body.userId}, receiver: {_id: to}, amount: amount });
// Commit the transaction
await session.commitTransaction();
res.json({
message: "Transfer successful"
});
});
它会抛出一个错误,指出需要firstName和lastName(我猜是在模式中指定的)。我尝试删除所需的属性,在这种情况下,交易有效...但新创建的记录中不存在发送者/接收者的名字或姓氏。
所以,问题是:如何在请求中只提供发送者和接收者的 _id,并将 _id、firstName、lastName 全部保存在交易集合中创建的记录中?
目的:我想创建一个页面,用户可以在其中查看他们最近的交易,因此最好将名称包含在交易集合本身中,否则我将不得不进行单独的数据库调用来获取该名称。
非常感谢您能走到这一步。愿平安与你同在。
您可以修改您的
transactionSchema
,使 sender
和 receiver
只是键,其值为 ObjectId
,对应于有效的 User._id
。
const transactionSchema = new mongoose.Schema({
sender: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
},
receiver: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true
},
amount: {
type: Number,
required: true
}
});
现在,当您创建
Transaction
文档时,您可以简单地执行以下操作:
await TransactionModel.create({
sender: req.body.userId,
receiver: to,
amount: amount
});
每当您对
transactions
集合进行查询并且想要获取每个 sender
和 receiver
文档的详细信息时,您可以使用 populate
,如下所示:
const transaction = await TransactionModel.find()
.populate('sender')
.populate('receiver');
如果您只想要
firstName
和lastName
,您可以这样做:
const transaction = await TransactionModel.find()
.populate({path: 'sender', select: 'firstName lastName'})
.populate({path: 'receiver', select: 'firstName lastName'});