【问题标题】:Merge two objects in mongoose合并猫鼬中的两个对象
【发布时间】:2016-06-29 09:08:14
【问题描述】:

我在 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",

【问题讨论】:

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


    【解决方案1】:

    在您的情况下,人口将是理想的。来自docs

    填充是自动替换指定的过程 文档中的路径以及来自其他集合的文档。

    Population 将无缝帮助您将 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!' });
    });
    

    【讨论】:

    • 感谢您给我一个想法,但在我的应用程序中,我有超过 15 个与用户收藏相关的收藏,在这种情况下,我不喜欢将所有收藏引用都放在用户收藏中。
    【解决方案2】:

    请试试这个,或者您可以使用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);
                        }
                    }
                });
            });
    
        }
    })
    

    【讨论】:

      【解决方案3】:

      您可以使用实现mongodb aggregationaggreate

      示例代码可能如下所示:

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-16
        • 2020-01-20
        • 2015-12-28
        • 2017-06-20
        • 2021-05-06
        • 1970-01-01
        相关资源
        最近更新 更多