我可能已经烧坏了,但我有以下型号:
用户
const mongoose = require('mongoose');
const validate = require('mongoose-validator');
const Post = require('./post');
let UserSchema = mongoose.Schema({
firstName: { type: String, required: true },
lastName: { type: String, required: true },
email: {
type: String, required: true, lowercase: true, trim: true, unique: true, index: true,
validate: [validate({ validator: 'isEmail', message: 'Invalid Email!' })]
},
posts: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Post' }]
})
module.exports = mongoose.model('User', UserSchema);
帖子
const _ = require('lodash');
const mongoose = require('mongoose');
const User = require('./user');
let PostSchema = mongoose.Schema({
user: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
title: { type: String, required: true },
body: { type: String, require: true }
})
PostSchema.post('save', async function (next) {
await User.update({ _id: this.user }, { $push: { posts: this._id } })
return next();
})
module.exports = mongoose.model('Post', PostSchema);
当尝试添加新帖子时,后保存挂钩会运行,但我收到错误User.update不是一个函数(同样适用于findOneAndUpdate,findOne等)。
我可以从应用程序的其余部分调用user.update而不会出现问题,所以不确定这里发生了什么。两个模型都在同一目录中。
答案 0 :(得分:1)
您错过的是post
中间件将第一个参数作为"文档"而不是next
处理程序:
const { Schema } = mongoose = require('mongoose');
const userSchema = new Schema({
firstName: String,
lastName: String,
posts: [{ type: Schema.Types.ObjectId, ref: 'Post' }]
});
const { Schema } = mongoose = require('mongoose');
const User = require('./user');
const postSchema = new Schema({
user: { type: Schema.Types.ObjectId, ref: 'User' },
title: String,
body: String
});
// note that first argument is the "document" as in "post" once it was created
postSchema.post('save', async function(doc, next) {
await User.update({ _id: doc.user._id },{ $push: { posts: doc._id } });
next();
});
const { Schema } = mongoose = require('mongoose');
const User = require('./user');
const Post = require('./post');
const uri = 'mongodb://localhost/posttest';
mongoose.set('debug', true);
mongoose.Promise = global.Promise;
const log = data => console.log(JSON.stringify(data, undefined, 2));
(async function() {
try {
const conn = await mongoose.connect(uri);
await Promise.all(Object.entries(conn.models).map(([k,m]) => m.remove()));
let user = await User.create({ firstName: 'Ted', lastName: 'Logan' });
let post = new Post({ user: user._id, title: 'Hi', body: 'Whoa!' });
post = await post.save();
mongoose.disconnect();
} catch(e) {
console.error(e)
} finally {
process.exit()
}
})()
返回:
Mongoose: users.remove({}, {})
Mongoose: posts.remove({}, {})
Mongoose: users.insertOne({ posts: [], _id: ObjectId("5b0217001b5a55208150cc9b"), firstName: 'Ted', lastName: 'Logan', __v: 0 })
Mongoose: posts.insertOne({ _id: ObjectId("5b0217001b5a55208150cc9c"), user: ObjectId("5b0217001b5a55208150cc9b"), title: 'Hi', body: 'Whoa!', __v: 0 })
Mongoose: users.update({ _id: ObjectId("5b0217001b5a55208150cc9b") }, { '$push': { posts: ObjectId("5b0217001b5a55208150cc9c") } }, {})
显示更新以正确的详细信息触发。
在良好的设计中,你真的应该避免这种情况,只需从posts
模型中删除User
数组即可。您始终可以使用virtual代替:
userSchema.virtual('posts', {
ref: 'Post',
localField: '_id',
foreignField: 'user'
})
或者只是通过$lookup
获取数据:
User.aggregate([
{ "$match": { "_id": userId } }
{ "$lookup": {
"from": Post.collection.name,
"localField": "_id",
"foreignField": "user",
"as": "posts"
}}
])
在父母"上存储和维护相关ObjectId
值"的数组;是一种"反模式"并导致不必要的开销,例如在两个地方写作,你只需要一个"一个"。
一般来说,你应该选择嵌入"首先",并且只考虑"引用"是否以及何时应用程序的使用模式实际需要它。简单地使用不是为此设计的数据库引擎复制RDBMS的相同模式并不是利用它的最佳方式。