我在mongoose的user.js
和userProfile.js
中有两个模型,我想使用连接查询获取文档,但我没有使用 ref 在用户架构中,所以我有如下代码:
user.js的
var userSchema = new Schema({
nick_name:{type:String},
email: {type: String},
password: {type: String},
is_active:{type:String,enum:['1','0'],default:"1"},
},{ collection: 'user'});
userProfile.js
var userProfileSchema = new Schema({
user_id:{type:Schema.Types.ObjectId, ref:'User'},
first_name:{type:String},
last_name:{type:String},
address:{type:String},
country:{type:String},
state:{type:String},
city:{type:String},
gender:{type:String,enum:['m','f','o'],default:"m"},
is_active:{type:String,enum:['1','0'],default:"1"},
},{ collection: 'userProfile'});
server.js
app.get('/api/userLists', function(req, res) {
User.find({},"nick_name email",function(err, user) {
if(err) {
res.json(err);
} else {
var userIds = user.map(function(obj){
return obj._id;
});
UserProfile.find({user_id:{$in:userIds}},function(err,userProfiles){
if(err){
res.json(userProfiles);
console.log(userProfiles);
}else{
---------------------------------
-What to do here, I have no idea.-
---------------------------------
res.json(user);
}
});
}
});
});
预期输出如下
{
"nick_name" : "laxman",
"email" : "laxman@mailinator.com",
"first_name" : "my first name",
"last_name" : "my last name",
"address" : "my address",
"country" : "my country",
"state" : "my state",
"city" : "my city",
"gender" : "m",
}
**OR**
{
"nick_name" : "laxman",
"email" : "laxman@mailinator.com",
"profile" :{
"first_name" : "my first name",
"last_name" : "my last name",
"address" : "my address",
"country" : "my country",
"state" : "my state",
"city" : "my city",
"gender" : "m",
}
}
依赖关系
"express" => "version": "4.7.4",
"mongoose" => "version": "4.4.5",
"mongodb" => "version": "2.4.9",
"OS" => "ubuntu 14.04 lts 32bit",
答案 0 :(得分:3)
请尝试使用此功能,或者您可以使用async
或promise更简洁地制作代码。
MyUser.find({}, 'nick_name email', function(err, users){
if (err)
console.log(err);
else {
var len = users.length;
var curIdx = 0;
var newUsers = [];
users.forEach(function(user) {
UserProfile.findOne({user_id: user._id}, function(err, ret) {
if (err)
console.log(err);
else{
// combine those two objects here...
user.set('profile', ret.toJSON(), {strict: false})
newUsers.push(user);
++curIdx;
if (curIdx == len) {
//console.log(newUsers);
res.json(newUsers);
}
}
});
});
}
})
答案 1 :(得分:1)
在您的情况下,人口将是理想的。来自 docs :
人口是自动替换指定的过程 文档中包含来自其他集合的文档的路径。
人口将无缝地帮助您将Profile
集合中的数据导入您的User
模型。例如,以json格式获取第二个输出
{
"nick_name": "laxman",
"email": "laxman@mailinator.com",
"profile": {
"first_name" : "my first name",
"last_name" : "my last name",
"address" : "my address",
"country" : "my country",
"state" : "my state",
"city" : "my city",
"gender" : "m",
}
}
使用您可以采用的方法考虑以下示例。将您的User
架构更改为
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var userSchema = new Schema({
nick_name: { type: String },
email: { type: String },
password: { type: String },
profile: { type: Schema.Types.ObjectId, ref: 'UserProfile' }
},{ collection: 'user'});
module.exports = mongoose.model('User', userSchema);
在用户架构定义中,将主代理键添加到名为ObjectId
的用户配置文件中,在数据中引用为_id
以获取填充功能。这将是用于引用UserProfile
集合中的文档的密钥。
阅读数据
这是Mongoose人群通过其 populate()
函数读取文档非常简单,容易和快速的地方。例如,要在用户上显示引用的profile
,请使用字符串中该字段的名称作为参数调用 populate()
方法,例如
app.get('/api/userLists', function(req, res) {
User.find({}, "nick_name email")
.populate("profile")
.exec(function(err, users) {
if(err) {
res.json(err);
} else {
res.json(users)
}
});
撰写数据
保存user
模型的数据时,还需要保存对配置文件的引用。例如,当创建新的User
时,您需要将UserProfile _id引用保存为配置文件字段:
var user = new User();
var profileId = "54b5659536cd5250a3a93bd3"; // <-- user profile id, for example.
user.nick_name = req.body.name;
user.email = req.body.email;
user.password = encrypt(req.body.password, user.nick_name);
user.profile = profileId;
user.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'user created!' });
});
答案 2 :(得分:1)
您可以使用aggreate来实现mongodb aggregation。
示例代码可能如下所示:
UserProfile.aggregate()
.match({user_id: {$in: userIds}})
.group({_id: "$user_id"}) // '$' is must
.project(...) // fields you want from UserProfile
.exec(function(err, result){
// do populate or something
})