美文网首页
mongo关联内嵌数组对象

mongo关联内嵌数组对象

作者: 秋_落 | 来源:发表于2019-06-07 15:04 被阅读0次

文章发布地址: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'
        }
    }
])

使用unwind对车信息进行解构,然后使用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关联内嵌数组对象

    文章发布地址:https://blog.qiuluo.xin/2019/03/16/mongo%E5%85%B3%...

  • mongo对内嵌数组的简单操作

    由于mongo的弱关联关系,导致mongo的内嵌数组会被频繁使用,以达到一定的"关联关系"。所以对mongo的数组...

  • mongodb之mgo操作bson入门

    mongo内嵌文档相关的查询语句

  • 深复制与浅复制

    概念: 浅复制与深复制都是只针对对象,数组,这些复杂类型。 浅复制指的是复制一个对象的一层属性,如果对象,数组内嵌...

  • mongo导出数组属性到csv

    mongo 的树状结构和csv文件的格式是不一样的,没有数组和子对象导出成csv没有问题遇到数组和子对象,可以通过...

  • 几个比较常用的 NPM 包

    # qs qs:处理 URL 查询字符串,支持内嵌对象和数组。简而言之,就是将对象和 URL 地址的参数互相转换(...

  • Shell数组、关联数组

    数组 定义数组 获取数组 关联数组 定义关联数组 获取关联数组

  • 关联数组与对象

    数组一般用数字索引取值,这是传统的数组。当不用数字索引而是明确给出下标,这样的数组叫关联数组 例如:var len...

  • js 中 浅克隆 | 深克隆

    浅克隆 浅克隆的对象的引用值是拷贝对象里的引用,这两个对象里面的引用(如对象里的数组或者内嵌对象)指向的地方是一致...

  • 2018-04-21

    第11章:持有对象 直接总结 1、数组将数字与对象关联起来 2、Collection保存单一元素,Map保存相关联...

网友评论

      本文标题:mongo关联内嵌数组对象

      本文链接:https://www.haomeiwen.com/subject/mvgmxctx.html