使用聚合 mongodb mongoose 将集合子子文档与其他集合子文档连接起来

Posted

技术标签:

【中文标题】使用聚合 mongodb mongoose 将集合子子文档与其他集合子文档连接起来【英文标题】:joining collections sub-subdocument with other collections subdocument using aggregate mongodb mongoose 【发布时间】:2020-12-05 07:32:32 【问题描述】:

所以,我有这种模型

const produkSchema = new mongoose.Schema(
    nama_produk: String,
    etalase: type: mongoose.Schema.Types.ObjectID, ref: 'kategori',
    kategori: type: mongoose.Schema.Types.ObjectID, ref: 'kategori',
    jenis: type: mongoose.Schema.Types.ObjectID, ref: 'kategori.jenis',
    bahan: String,
    warna: String,
    deskripsi: String,
    foto_produk: [String],
    harga: Number,
    link_bukalapak: String,
    link_shopee: String,
    link_tokopedia: String,
, 
    weights: 
        nama_produk: 5,
    ,
    timestamps: true
)

const tokoSchema = new mongoose.Schema(
    username: type: String, trim: true,
    password: type: String, required: true, select: false,
    merek: String,
    listMerek: [type: mongoose.Schema.Types.ObjectID, ref: 'produk'],
    deskripsi: String,
    follower: [type: mongoose.Schema.Types.ObjectID, ref: 'user'],
    email: type: String, trim: true, unique: true,
    instagram: String,
    whatsapp: String,
    website: String,
    alamat: String,
    foto_profil: String,
    bukalapak: String,
    shopee: String,
    tokopedia: String,
    fotoktp: String,
    banner: [
        gambar: type: String, required: true, trim: true,
        order: type: Number, required: true,
    ],
    produk: [produkSchema],
    etalase: [type: mongoose.Schema.Types.ObjectID, ref: 'kategori'],
    approve: type: Number, default: 0, // 0: pending, 1: reject, 2: approve
    populer: type: Boolean, default: false,
, timestamps: true);

exports.toko = mongoose.model("toko", tokoSchema);

const jenisSchema = new mongoose.Schema(
    label: String,
    gambar: String,
, timestamps: true)

const kategoriSchema = new mongoose.Schema(
    label: String,
    gambar: String,
    jenis: [jenisSchema]
, timestamps: true);

所以我想加入的是toko.produk.jeniskategori.jenis,但是如您所知,猫鼬不能在子文档之间填充,我尝试过toko.find().populate("produk.jenis", "label") 但它显示错误Schema hasn't been registered for model "kategori.jenis". Use mongoose.model(name, schema) 任何查询建议?我试过了


    $lookup: 
           "from": "kategoris",
           "localField": "produk.jenis",
           "foreignField": "jenis",
           "as": "jenisnya"
        

但它似乎不起作用,而是返回一个空数组。我该怎么办?我应该重新排列我的架构吗?

【问题讨论】:

@turivishal 我已经完成了,你可以在这里看到完整的代码pastebin.com/3DWJQRcp @turivishal 确定是pastebin.com/GNPEH94K @turivishal 或这里的简单数据一pastebin.com/ekHnimh8 【参考方案1】:

你可以试试这个,

$match你的条件 $unwind解构produk数组 $lookup 带管道 $unwind解构jenis数组 $match匹配jenis._id $project 仅显示 _idlabel $unwind 在路径中解构 produk.jenisnya $group by _id 并推入produk
db.toko.aggregate([
   $match:  _id: ObjectId("5f1d77aca53cb13980324c73")  ,
   $unwind: "$produk" ,
  
    $lookup: 
      from: "kategoris",
      as: "produk.jenisnya",
      let:  pjid: "$produk.jenis" ,
      pipeline: [
         $unwind: "$jenis" ,
         $match:  $expr:  $eq: ["$$pjid", "$jenis._id"]   ,
         $project:  "jenis._id": 1, "jenis.label": 1  
      ]
    
  ,
   $unwind:  path: "$produk.jenisnya"  ,
  
    $group: 
      _id: "$_id",
      produk:  $push: "$produk" ,
      // you can add otehr fields as well like alamat
      alamat:  $first: "$alamat" 
    
  
])

Playground

【讨论】:

你好,@turivishal 谢谢你的辛勤工作,非常感谢,查询运行顺利,但我认为jenisnya 显示所有数据,如何指定?我只想得到jenisnya.jenis._id jenisnya.jenis.label,我应该将它添加到$project吗?

以上是关于使用聚合 mongodb mongoose 将集合子子文档与其他集合子文档连接起来的主要内容,如果未能解决你的问题,请参考以下文章

mongoDB,带有 $sum 和 $count 的 mongoose 聚合查询

mongoDB,带有 $sum 和 $count 的 mongoose 聚合查询

MongoDB(猫鼬)聚合计数集合中特定 ObjectID 的实例

使用 mongodb 聚合获取父子关系

两个集合的聚合数组 mongodb

mongodb聚合匹配属性