不同表之间的数组关联

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

数据

主表的表结构如图所示:

{            
    name:{ type: String,required:true},
    accountNum:{type : String ,required :true},
    password:{type : String , required: true},
    // 购物车
    shopCart:[{
          shopID:{ type: mongoose.Schema.Types.ObjectId },
          number:{ type:String},
          color:{type :String},
          size:{type:String}
     }],
}

关联表的表结构如下所示

 {
      _id:MongoDB自动生成的,ObjectId类型的,
      shopName:{type: String , requied:true},
      imageUrl:{type: String , requied:true},
      price:{type: Number , requied:true},
      desc:[],   
      size:[],
      color:[],
  }
  

需要通过主表中shopCart的shopID与关联表中的_id关联。

取一个表的数据做例子,

// 主表的数据
  {
    "_id" : ObjectId("5ee65a64d89f7d3d28dea864"),
    "accountNum" : "gaotian",
    "name" : "那棵树的看法",
    "password" : "admin",
    "shopCart" : [ 
        {
            "_id" : ObjectId("5ee6c7fde9d2f42f58b788ec"),
            "shopID" : ObjectId("5ebfeabeb922ba458400c04d"),
            "number" : "2",
            "color" : "绅士灰",
            "size" : "L"
        },
       {
            "_id" : ObjectId("5ee6c7fde9d2f42f58b78845"),
            "shopID" : ObjectId("5ebfeda2fa462405dcfcd7aa"),
            "number" : "2",
            "color" : "绅士灰",
            "size" : "L"
        }
    ]
}

//关联表的数据
//非关键数据已经省略
{
    "_id" : ObjectId("5ebfeabeb922ba458400c04d"),
    "desc" : [ 
        ....
    ],
    "size" : [ 
      ....
    ],
    "color" : [ 
     ....
    ],
    "shopName" : "迪卡侬冰袖夏季户外跑步男女防晒手袖子防紫外线冰丝袖套护臂RUNC",
    "imageUrl" : "https://img.alicdn.com/bao/uploaded/i1/352469034/O1CN01in5YZN2GbceImjsLA_!!352469034-0-lubanu-s.jpg",
    "price" : 29.9,
    "__v" : 0
},
{
    "_id" : ObjectId("5ebfeda2fa462405dcfcd7aa"),
    "desc" : [ 
      ... 
    ],
    "size" : [ 
      ....
    ],
    "color" : [ 
      ....
    ],
    "shopName" : "森马白色t恤女短袖宽松韩版潮小众设计感上衣女夏季纯棉落肩ins潮",
    "imageUrl" : "https://img.alicdn.com/bao/uploaded/i4/397341302/O1CN01luzWS71LUMCukW1Vr-397341302.jpg",
    "price" : 49.9,
    "__v" : 0
}

关联代码

首先使用聚合函数,以用户表为主表,通过用户表中的数组对象shopCart中的shopID与商品表(shops)中的_id进行关联.

   this.ctx.model.User.aggregate([
              {
                $lookup:{
                  from:'shops',//关联的表
                  localField:'shopCart.shopID',//主表关联的字段
                  foreignField:'_id',//关联表的字段
                  as:"shop"//生成的数据放在shop中
                }
              }
  ])

通常主表中有很多数据对象,我们要找到我们想要的那个数据对象。比如我们要accountNum是 gaotian的用户。

   this.ctx.model.User.aggregate([
             {
               $lookup:{
                 from:'shops',//关联的表
                 localField:'shopCart.shopID',//主表关联的字段
                 foreignField:'_id',//关联表的字段
                 as:"shop"//生成的数据放在shop中
               }
             },{
             $match:{
                 "accountNum":'gaotian'  //找到我们想要关联的主表
               }
           }
 ])

这时候的返回的结果的结构也不是我们想要的,我们要是用使用unwind对数据进行结构,在使用project 进行重组。

  this.ctx.model.User.aggregate([
              {
                $lookup:{
                  from:'shops',//关联的表
                  localField:'shopCart.shopID',//主表关联的字段
                  foreignField:'_id',//关联表的字段
                  as:"shop"//生成的数据放在shop中
                }
              },{
              $match:{
                  "accountNum":'gaotian'  //找到我们想要关联的主表
                }
            },{
                $unwind:{
                  path:"$shop",
                  preserveNullAndEmptyArrays:true
                }
              },{
                $unwind:{
                  path:"$shopCart",
                  preserveNullAndEmptyArrays:true
                }
              }, {
                $project: {
                    "carid":'$shopCart._id',
                    'shopid':'$shop._id',
                    'shopName':"$shop.shopName",
                    'imageUrl': "$shop.imageUrl",
                    'price': "$shop.price",
                    "number":'$shopCart.number',
                    "size":'$shopCart.size',
                    "color":"$shopCart.color",
                    "isnumber":"$shop.isnumber",
                    'flag':{$eq :["$shopCart.shopID","$shop._id"]}
                }
            }
  ])

这个地方的unwind的作用说白了就是打散shop和shopCart这两组数据,打散之后你会发现shopCart和shop中的数据进行了两两配对,一共出现了四种结果。
project就是挑出你要显示的键名和键值,键名是自己起的。
但是他这是两两配对了,出来了四种结果,并没有把我们想要的。然后我们就可以用通过比较运算符来进行筛选。eq是等于运算符,如果shopCart.shopID和shop._id相等就会返回true。

image.png

  this.ctx.model.User.aggregate([
              {
                $lookup:{
                  from:'shops',//关联的表
                  localField:'shopCart.shopID',//主表关联的字段
                  foreignField:'_id',//关联表的字段
                  as:"shop"//生成的数据放在shop中
                }
              },{
              $match:{
                  "accountNum":'gaotian'  //找到我们想要关联的主表
                }
            },{
                $unwind:{
                  path:"$shop",
                  preserveNullAndEmptyArrays:true
                }
              },{
                $unwind:{
                  path:"$shopCart",
                  preserveNullAndEmptyArrays:true
                }
              }, {
                $project: {
                    "carid":'$shopCart._id',
                    'shopid':'$shop._id',
                    'shopName':"$shop.shopName",
                    'imageUrl': "$shop.imageUrl",
                    'price': "$shop.price",
                    "number":'$shopCart.number',
                    "size":'$shopCart.size',
                    "color":"$shopCart.color",
                    "isnumber":"$shop.isnumber",
                    'flag':{$eq :["$shopCart.shopID","$shop._id"]}
                }
            },{
              $match :{
                'flag':true
              }
            },
            {
              $project: {
                  'flag': 0
              }
          }          
  ])

然后我们可以在通过match筛选flag为true的数据,那这组就是我们想要的数据了。最后再加上一个文档重组。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355