我有两个Schema定义如下:
var WorksnapsTimeEntry = BaseSchema.extend({
student: {
type: Schema.ObjectId,
ref: 'Student'
},
timeEntries: {
type: Object
}
});
var StudentSchema = BaseSchema.extend({
firstName: {
type: String,
trim: true,
default: ''
// validate: [validateLocalStrategyProperty, 'Please fill in your first name']
},
lastName: {
type: String,
trim: true,
default: ''
// validate: [validateLocalStrategyProperty, 'Please fill in your last name']
},
displayName: {
type: String,
trim: true
},
municipality: {
type: String
}
});
我想循环通过每个学生并显示它的时间条目。到目前为止,我有这个代码显然不对,因为我还不知道如何加入WorksnapTimeEntry模式表。
Student.find({ status: 'student' })
.populate('student')
.exec(function (err, students) {
if (err) {
return res.status(400).send({
message: errorHandler.getErrorMessage(err)
});
}
_.forEach(students, function (student) {
// show student with his time entries....
});
res.json(students);
});
任何人都知道如何实现这样的目标?
答案 0 :(得分:17)
从版本3.2开始,您可以在聚合管道中使用$lookup来执行左外连接。
Student.aggregate([{
$lookup: {
from: "worksnapsTimeEntries", // collection name in db
localField: "_id",
foreignField: "student",
as: "worksnapsTimeEntries"
}
}]).exec(function(err, students) {
// students contain WorksnapsTimeEntries
});
答案 1 :(得分:9)
您不希望.populate()
在这里,而是您需要两个查询,其中第一个匹配Student
个对象以获取_id
值,第二个将使用{{3为那些“学生”匹配相应的WorksnapsTimeEntry
项目。
使用$in
只是为了避免一些缩进蠕变:
async.waterfall(
[
function(callback) {
Student.find({ "status": "student" },{ "_id": 1 },callback);
},
function(students,callback) {
WorksnapsTimeEntry.find({
"student": { "$in": students.map(function(el) {
return el._id
})
},callback);
}
],
function(err,results) {
if (err) {
// do something
} else {
// results are the matching entries
}
}
)
如果你真的必须,那么你可以在第二个查询中.populate("student")
从另一个表中获取已填充的项目。
相反的情况是查询WorksnapsTimeEntry
并返回“所有内容”,然后使用“匹配”查询选项过滤掉null
的{{1}}个结果:
.populate()
因此,这不是一个理想的行动,因为“数据库”并未过滤可能的大部分结果。
除非你有充分的理由不这样做,否则你可能“应该”“嵌入”数据。这样,集合中就可以使用WorksnapsTimeEntry.find().populate({
"path": "student",
"match": { "status": "student" }
}).exec(function(err,entries) {
// Now client side filter un-matched results
entries = entries.filter(function(entry) {
return entry.student != null;
});
// Anything not populated by the query condition is now removed
});
“等属性,并且不需要其他查询。
如果您正在使用像MongoDB这样的NoSQL解决方案,那么您应该接受它的概念,而不是坚持关系设计原则。如果你一直在建模关系,那么你也可以使用关系数据库,因为你不会从有其他方法处理它的解决方案中获得任何好处。
答案 2 :(得分:0)
为时已晚,但会帮助许多开发人员。 验证方式
<块引用>"mongodb": "^3.6.2", "猫鼬": "^5.10.8",
在 mongoose 中加入两个集合
ProductModel.find({} , (err,records)=>{
if(records)
//reurn records
else
// throw new Error('xyz')
})
.populate('category','name') //select only category name joined collection
//.populate('category') // Select all detail
.skip(0).limit(20)
//.sort(createdAt : '-1')
.exec()
产品模型架构
const CustomSchema = new Schema({
category:{
type: Schema.ObjectId,
ref: 'Category'
},
...
}, {timestamps:true}, {collection: 'products'});
module.exports = model('Product',CustomSchema)
类别模型架构
const CustomSchema = new Schema({
name: { type: String, required:true },
...
}, {collection: 'categories'});
module.exports = model('Category',CustomSchema)
答案 3 :(得分:0)
试试这个 code 在猫鼬中加入两个集合
Mongoose 加入两个集合创建架构
const { Schema, model} = require("mongoose");
const UserSchema = new Schema({
name:{
type: String,
required: true
},
email:{
type: String,
required: true
},
posts:[{
type: Schema.Types.ObjectId, ref: "Post"
}]
});
const PostSchema = new Schema({
title: String,
desc: String,
User: {type: Schema.Tpes.ObjectId, ref: "User"}
});
export const Post = model("Post", PostSchema);
export const User = model("User", UserSchema);
然后
try {
const user = User.create({
name:"Robert Look",
email: "phpcodingstuff@gmail.com"
})
try {
const post1 = Post.create({
title: "This is a first post",
desc: "this a a first description"
user: User._id // assign the _id from the user
});
} catch (err) {
console.log(err.message)
}
} catch (err) {
console.log(err.message)
}
阅读模型
User.findOne({
name: "Robert Look"
}).populate('posts').exec((err, user) =>{
if(err){
console.log(err)
}else{
console.log(users.posts[0].desc)
}
});
结论 我们在上面看到了如何使用 populate 我们还看到了如何使用 joining two documents in mongoose (MongoDB),如果您正确编写查询,那么您将获得一个好的结果或您的 JSON。