【问题标题】:Join to collections in mongodb加入 mongodb 中的集合
【发布时间】:2020-06-18 11:53:36
【问题描述】:

我试图从同一个 json 对象响应中的两个集合中获取数据。 我正在尝试使用 $lookup 加入这两个集合,但它不起作用:

db.getCollection('profiles').aggregate( [
 {
    { 
     $match: {_id: ObjectId(userId) } 
     },

     $lookup: {
                  from: "users",
                  localField: "user",
                  foreingField: "_id",
                  as: "user_data"  

                }
 }
])

在配置文件模型中,用户声明如下:

 user: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: [ true, 'A reference to a user must exist']
    },

这是我可以在控制台中看到的调试查询:

Mongoose: users.aggregate([ { '$match': { _id: 5eec20720ff19056d079e953 } }, { '$lookup': { from: 'profile', localField: '_id', foreignField: 'user', as: 'profile_data' } }], {})

【问题讨论】:

  • 英文标题:“在 JSON 对象上动态创建属性”用 SO 西班牙语发布。
  • db.user.aggregate([{ $unionWith: "Collection1" },{ $unionWith: "Collection2" }, ....])
  • 对不起,我在用西班牙语思考,我该如何编辑它?谢谢
  • 你的问题有点不清楚是usernamesurname 拐杖吗?
  • 您说的是profile 模型,但您写的是userhere: user: { type: Schema.Types.ObjectId, ref: 'User', required: [ true, 'A reference to a user must exist'] }。如果您可以放置​​模型的形状(甚至是部分),我会提供很大帮助。

标签: json mongodb


【解决方案1】:

好的,感谢 Armamedia 的回答,我终于找到了解决方案,但老实说,我想了解如何将这两个集合加入同一个 json 对象中。目前我像这样解决了它,有 2 个查询,一个是配置文件集合,第二个是用户集合。

   const profile = await getUserProfile( userId, select );
   const user   = await User.find({"_id": userId}).select('email _id');

   return res.json({
        code: 200,
        data: {
            "name": profile[0].name,
            "email": user[0].email,
            "rate": profile[0].rate,    
        }

    })

【讨论】:

    【解决方案2】:

    跳到... 你的问题有点不清楚。姓名和姓氏是否来自用户?如果是这样,您可以执行以下操作:

    const response = {
        code: 200,
        profile: {
            name: user.name,
            surname: user.surname,
            email: profile.email
        }
    }
    

    然后您可以将其字符串化:

    JSON.stringify(response);
    

    或者像这样发送(如果您使用的是快递):

    response.send(response);
    

    直到这里...


    编辑:现在我明白了问题所在,这就是答案:

    假设您的模型如下所示,您存储的数据如下:

    const User = mongoose.model(
        'User',
        new mongoose.Schema({
            email: {
                type: String,
            },
        })
    );
    const Profile = mongoose.model(
        'Profile',
        new mongoose.Schema({
            name: {
                type: String,
            },
            rate: {
                type: Number,
            },
            user: {
                type: mongoose.Schema.Types.ObjectId,
                ref: User,
            },
        })
    );
    
    async function createAndSaveThem() {
        let user = new User({
            email: 'blah@blah.blah',
        });
        await user.save();
        let profile = new Profile({
            name: 'You',
            rate: 4,
            user: user._id,
        });
        await profile.save();
    }
    
    try {
        createAndSaveThem();
    } catch (error) {
        console.log(error);
    }
    

    您可以按照自己的方式处理数据,如下所示(无需汇总):

    async function getThem() {
        const profile = await Profile.findOne({ name: 'You'}).populate('user');
    
        const response = {
            code: 200,
            date: {
                name: profile.name,
                rate: profile.rate,
                email: profile.user.email
            }
        }    
        console.log('1', response); 
    }
    
    try {
        getThem();
    } catch (error) {
        console.log(error);
    }
    

    或者这个(使用聚合):

    async function getThemWithAggregate() {
        let profile = await Profile.aggregate([
            { $match: { name: 'You' } },
            {
                $lookup: {
                    from: 'users',
                    localField: 'user',
                    foreignField: '_id',
                    as: 'user',
                },
            },
            { $unwind: '$user' },
            { $project: { name: 1, rate: 1, email: '$user.email', _id: 0 } },
        ]);
        const response = {
            code: 200,
            date: profile[0]
        }    
        console.log(JSON.stringify(response,0,2)); 
    }
    
    try {
        getThemWithAggregate();
    } catch (error) {
        console.log(error);
    }
    

    两者都会输出:

    {
      "code": 200,
      "date": {
        "name": "You",
        "rate": 4,
        "email": "blah@blah.blah"
      }
    }
    

    【讨论】:

    • 是的,你是对的,不是很清楚,这就是我再次编辑我的问题的原因。正如我上面解释的,我只想加入到同一个 json 响应中的集合。谢谢
    • 好的,感谢 Armamedia,我可以找到解决方案,但老实说,我想了解如何加入收藏。
    • 我认为人口将要走的路。但我需要你模型的形状。
    • 对不起,我不得不再次纠正自己,我按照你说的用人口解决了它,只是创建了一个新对象并将其添加到响应中(而不是原始对象)。非常感谢。
    • 欢迎您。既然我理解了问题,我就编辑了答案。只是不要忘记将我的答案标记为正确。另外,如果您需要我添加任何内容或进行编辑,请告诉我。
    猜你喜欢
    • 2016-10-22
    • 1970-01-01
    • 2020-05-12
    • 2018-04-11
    • 2018-06-23
    • 2012-09-15
    • 1970-01-01
    • 1970-01-01
    • 2018-08-21
    相关资源
    最近更新 更多