收藏
回答

如何用lookup一次调用,得到多级关联的数据?

新人接触数据库 (超市)

一级类目集合 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' }

} ,

....

}

......

求大神指点,如何做?还是说我的数据结构是不对的??




回答关注问题邀请回答
收藏

4 个回答

  • sea
    sea
    2021-07-26

    楼上的回答很无语,什么叫无法实现多级嵌套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

    2021-07-26
    有用 5
    回复 4
    • Zhao ZW
      Zhao ZW
      2021-07-30
      感谢您的回复,这样的回复才叫好回答!!
      2021-07-30
      回复
    • sea
      sea
      2021-07-30回复Zhao ZW
      不客气~
      2021-07-30
      回复
    • 27
      27
      2022-05-07
      谢谢,有用。
      2022-05-07
      回复
    • 稳住,我们能赢
      稳住,我们能赢
      2023-12-01
      有用
      2023-12-01
      回复
  • 郑旭东
    郑旭东
    2021-02-22

    lookup嵌套查询性能低下,小数据量下可以使用,批量嵌套,超过100个嵌套可能就卡了。慎用

    2021-02-22
    有用 1
    回复 4
    • Zhao ZW
      Zhao ZW
      2021-02-22
      真的啊,谢谢啊!!!
      2021-02-22
      1
      回复
    • Zhao ZW
      Zhao ZW
      2021-02-22
      关键我不会嵌套使用,呵呵 只会一次lookup,如何再这次lookup下再lookup一下没一项??大神指点下,写法啊!
      2021-02-22
      1
      回复
    • 郑旭东
      郑旭东
      2021-02-22回复Zhao ZW
      我意思lookup本身相当于嵌套,多层lookup没法搞吧。
      2021-02-22
      1
      回复
    • Zhao ZW
      Zhao ZW
      2021-02-22回复郑旭东
      谢谢了!!!大神
      2021-02-22
      回复
  • 跨商通
    跨商通
    2021-02-16

    参考一下我们的商品表设计方案:实践证明比较好用:

    product:{category:'水果',category2:'热带水果',name:'苹果'}

    一个表搞定商品分类和商品详情;

    查询所有分类:

    aggregate().group({_id:"$category"})得到所有一级商品分类;

    aggregate().group({_id:{c1:"$category",c2:"$category2"})得到一级分类和二级分类的组合

    aggregate().match({category:'水果'}).group({_id:"$category2"})得到水果下面的所有二级分类

    2021-02-16
    有用 1
    回复 3
    • Zhao ZW
      Zhao ZW
      2021-02-16
      大神啊,点赞你!自己琢磨学习太累了。真希望有你们这个的团队在身边。感谢您的回答!
      2021-02-16
      1
      回复
    • Zhao ZW
      Zhao ZW
      2021-02-16
      请问,您对小程序的cms内容管理这个功能有什么看法?你们的后台管理是什么方案?
      2021-02-16
      1
      回复
    • 跨商通
      跨商通
      2021-02-17回复Zhao ZW
      我们暂时没有用到网页CMS。我们的店家管理功能也是做在小程序里的(只有店主和店员可见),服务商管理功能也是做在小程序里的。点我头像里有说明。
      2021-02-17
      1
      回复
  • 小冷
    小冷
    发表于移动端
    2021-02-16
    2021-02-16
    有用
    回复
登录 后发表内容
问题标签