合并猫鼬中的两个对象

时间:2016-03-14 10:57:52

标签: javascript node.js mongodb mongoose mongodb-query

我在mongoose的user.jsuserProfile.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",

3 个答案:

答案 0 :(得分:3)

请尝试使用此功能,或者您可以使用asyncpromise更简洁地制作代码。

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 
    })

您可能也想知道how to populate the aggregate result