mongo关联内嵌数组对象

文章发布地址:https://blog.qiuluo.xin/2019/03/16/mongo%E5%85%B3%E8%81%94%E5%86%85%E5%B5%8C%E6%95%B0%E7%BB%84%E5%AF%B9%E8%B1%A1/

我的需求是主表中的一个字段,关联另一个表内嵌数组中的对象。

简化一下表结构,如下所示

订单表中carId关联了用户的本田车

// orders
{
    _id: ObjectId("5c861c98a352df5ea4739b0f"),
    carId: ObjectId("5c7fc109cac1902780c6e4df")
}
// users
{
    "_id" : ObjectId("5c88678ecb5fc635704d84bc"),
    "carMessage" : [                                        // 汽车信息
        {
            "_id" : ObjectId("5c8b047e69e25054877d1da5"),
            "brand" : "本田",
            "series" : "CRV"
        }, 
        {
            "_id" : ObjectId("5c8b049369e25054877d1da6"),
            "brand" : "大众",
            "series" : "探歌"
        }
    ]
}

进行表关联

首先使用聚合函数以订单表为主表对人员表中的汽车进行关联

直接将users的carId和users的carMessage._id关联

db.getCollection("orders").aggregate([
    {
        $lookup:{
            from: 'users',
            localField: 'carId',
            foreignField: 'carMessage._id',
            as: "car"
        }
    }
])

结果如下:

/* 1 */
{
    "_id" : ObjectId("5c8c96001936e8f1204a7dbe"),
    "carId" : ObjectId("5c8b047e69e25054877d1da5"),
    "car" : [ 
        {
            "_id" : ObjectId("5c8c96121936e8f1204a7dc7"),
            "carMessage" : [ 
                {
                    "_id" : ObjectId("5c8b047e69e25054877d1da5"),
                    "brand" : "本田",
                    "series" : "CRV"
                }, 
                {
                    "_id" : ObjectId("5c8b049369e25054877d1da6"),
                    "brand" : "大众",
                    "series" : "探歌"
                }
            ]
        }
    ]
}

结果查出了本田车所在的整条记录,显然不是我们想要的。

对文档结构重组

db.getCollection("orders").aggregate([
    {
        $lookup:{
            from: 'users',
            localField: 'carId',
            foreignField: 'carMessage._id',
            as: "car"
        }
    },
    {
        $unwind: {
            path: "$car",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        $unwind: {
            path: "$car.carMessage",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        $project: {
            '_id': 1,
            'carId': 1,
            'car': '$car.carMessage'
        }
    }
])

使用project进行重组展示。就得到了下面的结果。

/* 1 */
{
    "_id" : ObjectId("5c8c96001936e8f1204a7dbe"),
    "carId" : ObjectId("5c8b047e69e25054877d1da5"),
    "car" : {
        "_id" : ObjectId("5c8b047e69e25054877d1da5"),
        "brand" : "本田",
        "series" : "CRV"
    }
}

/* 2 */
{
    "_id" : ObjectId("5c8c96001936e8f1204a7dbe"),
    "carId" : ObjectId("5c8b047e69e25054877d1da5"),
    "car" : {
        "_id" : ObjectId("5c8b049369e25054877d1da6"),
        "brand" : "大众",
        "series" : "探歌"
    }
}

去掉了其它没用的字段,但是多出了本田车外的其它车信息。

去除多余文档

我们只需要得到其中carId和car._id相等的文档,就是想要的结果了,但是mongodb不像sql数据库可以直接查询两个字段相等的文档,所以我们只能使用其它方法来实现。

mongo虽然不能直接查询相等的文档结果,但是可以得到两字段是否相等的布尔值

首先在$project重组文档的时候加入一个flag,放入字段是否相等的结果

'flag': { "$eq": ["$carId", "$car.carMessage._id"] }

然后再加入一个查询条件来过滤掉不符合条件的文档

{
    $match: {
        'flag': true
    }
}

最后再加上一个文档重组,得到想要的数据结构

{
    $project: {
        'carId': 0,
        'flag': 0
    }
}

最后我们需要执行的聚合函数就是下面这样的

db.getCollection("orders").aggregate([
    {
        $lookup:{
            from: 'users',
            localField: 'carId',
            foreignField: 'carMessage._id',
            as: "car"
        }
    },
    {
        $unwind: {
            path: "$car",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        $unwind: {
            path: "$car.carMessage",
            preserveNullAndEmptyArrays: true
        }
    },
    {
        $project: {
            '_id': 1,
            'carId': 1,
            'car': '$car.carMessage',
            'flag': {$eq: ["$carId", "$car.carMessage._id"]}
        }
    },
    {
        $match: {
            'flag': true
        }
    },
    {
        $project: {
            'carId': 0,
            'flag': 0
        }
    }
])

这是最终得到的结果:

/* 1 */
{
    "_id" : ObjectId("5c8c96001936e8f1204a7dbe"),
    "car" : {
        "_id" : ObjectId("5c8b047e69e25054877d1da5"),
        "brand" : "本田",
        "series" : "CRV"
    }
}

你可能感兴趣的:(mongo关联内嵌数组对象)