新人接触数据库 (超市)
一级类目集合 xxx : 【 { id:0001,name:水果 },{id:002,name:蔬菜}......】
二级类目集合 yyy : 【 { id:1001,name:'热带水果',category:'0001'},{id:1002,name:'非热带水果',category:'0001'},......】
商品集合 zzz: 【 { id:'3001',name:'香蕉',category:'1001' } , { id:'3002',name:'苹果',category:'1002' }......】
只会通过 db.collection('xxx').aggregate().lookup({
from:'zzz',
localField:'_id',
foreignField:'category',
as:'list'
}).end()
得到关联的一层数据。
如何 从 通过 db.collection('xxx') 获得被关联的数据list中的每一项也被关联的数据(即获取多层关联的数据,包含最终的商品数据)
好比得到的数据如下 【 { id:0001,name:水果,list:【
{ id:1001,name:'热带水果',category:'0001',
list: 【 { id:'3001',name:'香蕉',category:'1001' } ,
{ id:'3002',name:'苹果',category:'1002' }
】
} ,
....
】
}
......
】
求大神指点,如何做?还是说我的数据结构是不对的??
楼上的回答很无语,什么叫无法实现多级嵌套lookup......
假设我有四个集合
菜品的大类,菜单明细,菜品的规格,菜品规格的具体选项,
这么设置也是为了方便CMS内容管理
为什么建表多用关联而不是用json嵌套?
最后使用CMS是客户,
客户没有代码基础的,你让他写JSON键值对,搞笑....
至于二楼提到的product:{category:'水果',category2:'热带水果',name:'苹果'}
这种方法,脑回路清奇,但和CMS完全不搭边,客户肯定不买账
难道你要我自己修改枚举类型?
回到正题,如何多层lookup嵌套?
按照我的数据,菜品类别-->菜品介绍--->菜品规格--->菜品规格选项
至少三个loopup,怎么写?
答案只有一个就是pipeline的嵌套!!!
先从简单的来:两层嵌套
两层嵌套:lookup(pipeline)+loopup(普通内外键相等):
db.collection("goodsClassMain").aggregate() .lookup( { from: "goodsClassDetail", let: { id: '$_id', }, pipeline: $.pipeline().match(_.expr($.in(["$$id", "$classMain"]))) .lookup( { from: "propertyClassMain", localField: 'property', foreignField: '_id', as: "propertyInfo", } ).project( { imageShow:0, imageSwiper:0 } ) .done(), as: 'goods', } ).project( { _createTime: 0, _updateTime: 0, icon: 0, "goods.classMain":0, "goods.property":0, } ).limit(1) .end()
这里为方便显示,project了很多字段不显示
第一层利用管道looku生成goods字段
管道继续接力
第二层利用内外键相等,生成了propertyInfo字段,
内外键一搞,就断子绝孙罗
最后结果
[ { "_id": "b00064a760fcce9b2a1a19a24df15e4c", "name": "肠粉世家", "goods": [ { "content": "本店招牌广式小吃。主料有粘米粉,辅料有猪油、酱油、玉米淀粉、清水、鸡蛋、瘦肉末等", "inventory": 20, "onSale": true, "priceBasic": 8, "title": "鸡蛋瘦肉肠粉", "_createTime": 1627181064482, "_updateTime": 1627191005873, "propertyInfo": [ { "_id": "28ee4e3e60fcc9092d728b837549ab43", "propertyPool": [ "79550af260fcc8f329537c3226c930c4", "28ee4e3e60fcc9f42d72da460f2aadbb", "79550af260fccb5229542bc973355b3d", "28ee4e3e60fccb632d7351c46f425dae" ], "typeDes": "好的口味,吃半爽倍", "typeName": "口味", "_createTime": 1627179273822, "_updateTime": 1627179891902, "propertySelectType": 1 }, { "_id": "79550af260fcc9bc2953b5cd353f0d07", "propertyPool": [ "b00064a760fcc9182a18614936b720e8", "b00064a760fcc96b2a187a3654d630eb", "b00064a760fcc9762a187d5c65e7a997" ], "typeDes": "爱你,所以宠你.", "typeName": "配料偏好", "_createTime": 1627179452935, "_updateTime": 1627179811113, "propertySelectType": 0 }, { "_id": "b00064a760fccbb02a1927f838c35ffd", "propertyPool": [ "28ee4e3e60fccbcf2d73769f6cd9acf5", "b00064a760fccbe12a1937c85f4cabbf", "28ee4e3e60fccbfa2d7384415a5346d7" ], "propertySelectType": 0, "typeDes": "谁知盘中餐,粒粒皆辛苦\n适合的,才是最好的", "typeName": "分量", "_createTime": 1627179957245, "_updateTime": 1627180039461 } ] }, ]
显然不够,还得继续嵌套,
菜品规格的选项还没嵌套出来
要想嵌套继续搞,管道接力少不了
不断用pipeline即可
db.collection("goodsClassMain").aggregate() .lookup( { from: "goodsClassDetail", let: { id: '$_id', }, pipeline: $.pipeline().match(_.expr($.in(["$$id", "$classMain"]))) .lookup( { from: "propertyClassMain", let: { property_: '$property', }, pipeline: $.pipeline() .match(_.expr( $.in(['$_id', '$$property_']), )) .project({ _id: 0, // propertyPool: 0, _createTime: 0, _updateTime: 0, }).lookup( { from: "propertyDetail", let: { propertyPool: '$propertyPool', }, pipeline: $.pipeline().match( _.expr($.in(["$_id", "$$propertyPool"])) ).project({ _id: 0, propertyPool:0, _createTime: 0, _updateTime: 0, propertyType:0 }).done() , as: "propertyDetalPool" }, ).project({ propertyPool:0, }) .done(), as: "propertyInfo", } ) .project( { property: 0, classMain: 0, _createTime: 0, _updateTime: 0, imageShow: 0, imageSwiper: 0 } ) .done(), as: 'goods', } ).project( { icon: 0, _createTime: 0, _updateTime: 0, imageShow: 0, imageSwiper: 0 } ).end()
结果如下
[ { "_id": "b00064a760fcce9b2a1a19a24df15e4c", "name": "肠粉世家", "goods": [ { "_id": "28ee4e3e60fcd0082d74eec702e14b95", "content": "本店招牌广式小吃。主料有粘米粉,辅料有猪油、酱油、玉米淀粉、清水、鸡蛋、瘦肉末等", "inventory": 20, "onSale": true, "priceBasic": 8, "title": "鸡蛋瘦肉肠粉", "propertyInfo": [ { "typeDes": "好的口味,吃半爽倍", "typeName": "口味", "propertySelectType": 1, "propertyDetalPool": [ { "propertyDefault": false, "propertyName": "去蒜", "propertyPriceChange": 0 }, { "propertyDefault": false, "propertyName": "少油", "propertyPriceChange": 0 } ] }, { "typeDes": "爱你,所以宠你.", "typeName": "配料偏好", "propertySelectType": 0, "propertyDetalPool": [ { "propertyDefault": false, "propertyName": "加麻", "propertyPriceChange": 0 }, { "propertyDefault": false, "propertyName": "中辣", "propertyPriceChange": 0 }, ] }, ] }, ]
完美实现了三层嵌套:分别生成goos,propertyPool(project掉了),propertyInfo ,propertyDetalPool三个字段
最后建议楼主多看mongodb文档,小程序云数据库基本就是云mongodb,
去搜素资料的时候,把云数据库---->mongodb,也许答案更靠谱
mongodb官方文档
https://docs.mongodb.com/manual/introduction/
mongodb嵌套lookup
https://www.kejisen.com/article/111750540.html
lookup嵌套查询性能低下,小数据量下可以使用,批量嵌套,超过100个嵌套可能就卡了。慎用
参考一下我们的商品表设计方案:实践证明比较好用:
product:{category:'水果',category2:'热带水果',name:'苹果'}
一个表搞定商品分类和商品详情;
查询所有分类:
aggregate().group({_id:"$category"})得到所有一级商品分类;
aggregate().group({_id:{c1:"$category",c2:"$category2"})得到一级分类和二级分类的组合
aggregate().match({category:'水果'}).group({_id:"$category2"})得到水果下面的所有二级分类