mongo關(guān)聯(lián)內(nèi)嵌數(shù)組對象

文章發(fā)布地址: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/

我的需求是主表中的一個字段,關(guān)聯(lián)另一個表內(nèi)嵌數(shù)組中的對象。

簡化一下表結(jié)構(gòu),如下所示

訂單表中carId關(guān)聯(lián)了用戶的本田車

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

進(jìn)行表關(guān)聯(lián)

首先使用聚合函數(shù)以訂單表為主表對人員表中的汽車進(jìn)行關(guān)聯(lián)

直接將users的carId和users的carMessage._id關(guān)聯(lián)

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

結(jié)果如下:

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

結(jié)果查出了本田車所在的整條記錄,顯然不是我們想要的。

對文檔結(jié)構(gòu)重組

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對車信息進(jìn)行解構(gòu),然后使用project進(jìn)行重組展示。就得到了下面的結(jié)果。

/* 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相等的文檔,就是想要的結(jié)果了,但是mongodb不像sql數(shù)據(jù)庫可以直接查詢兩個字段相等的文檔,所以我們只能使用其它方法來實(shí)現(xiàn)。

mongo雖然不能直接查詢相等的文檔結(jié)果,但是可以得到兩字段是否相等的布爾值

首先在$project重組文檔的時候加入一個flag,放入字段是否相等的結(jié)果

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

然后再加入一個查詢條件來過濾掉不符合條件的文檔

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

最后再加上一個文檔重組,得到想要的數(shù)據(jù)結(jié)構(gòu)

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

最后我們需要執(zhí)行的聚合函數(shù)就是下面這樣的

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

這是最終得到的結(jié)果:

/* 1 */
{
    "_id" : ObjectId("5c8c96001936e8f1204a7dbe"),
    "car" : {
        "_id" : ObjectId("5c8b047e69e25054877d1da5"),
        "brand" : "本田",
        "series" : "CRV"
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容