如何解决mongodb查询以将子文档显示为主文档并对其进行分页
首先,我有这种类型的模型:
const produkSchema = new mongoose.Schema({
nama_produk: String,etalase: {type: mongoose.Schema.Types.ObjectID,ref: 'kategori'},kategori: {type: mongoose.Schema.Types.ObjectID,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,link_lazada: String,link_website: String,display: {type: Boolean,default: false},},{
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'}],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,// order: {type: Number,required: true},}],produk: [produkSchema],etalase: [{type: mongoose.Schema.Types.ObjectID,ref: 'kategori'}],// etalase: [{
// kategori: {type: mongoose.Schema.Types.ObjectID,// order: {Number}
// }],approve: {type: Number,default: 0},// 0: pending,1: reject,2: approve
populer: {type: Boolean,gambar_populer: [String],pilihan: {type: Boolean,{timestamps: true});
,我有一个端点可以用以下代码过滤produkSchema
:
exports.filterProduk = (req,res) => {
const {merek,warna,kategori,jenis,hargaAwal,hargaAkhir,skip,limit} = req.body
let query = {}
const $and = []
if (merek) {
$and.push({$or: merek.map(id => ({_id: mongoose.Types.ObjectId(id)}))})
}
if (warna) {
$and.push({$or: warna.map(warna => ({"produk.warna": warna}))})
}
if (kategori) {
query["produk.etalase"] = mongoose.Types.ObjectId(kategori)
}
if (jenis) {
$and.push({$or: jenis.map(id => ({"produk.jenis": mongoose.Types.ObjectId(id)}))})
}
if (hargaAwal !== '') {
query["produk.harga"] = {
$gte: parseInt(hargaAwal),}
}
if (hargaAkhir !== '') {
query["produk.harga"] = {
$lte: parseInt(hargaAkhir)
}
}
if ($and.length > 0) {
query = {$and,...query}
}
toko.aggregate([
{$unwind: '$produk'},{$match: query},{
$lookup: {
from: "kategoris",as: "produk.etalase",let: {pjid: "$produk.jenis"},pipeline: [
{$unwind: "$jenis"},{$match: {$expr: {$eq: ["$$pjid","$jenis._id"]}}},{
$project: {
"jenis._id": 1,"jenis.label": 1
}
}
]
}
},{$unwind: {path: "$produk.etalase"}},{$group: {_id: '$_id',produk: {$push: '$produk'},foto_profil: {$first: '$foto_profil'}}},{$limit: skip + limit},{$skip: skip}
])
.then(async data => {
res.status(200).json({data,prefix: {produk: "uploads/produk",toko: "uploads/toko"}})
})
}
实际结果是:
[
{_id: blabla,foto_profil: "blabla",produk:[{nama_produk: "blabla",bahan: "blabla",...rest ProdukSchema as query}]
},{_id: blabla,...rest ProdukSchema as query}]
}
]
预期:
[
{nama_produk: "blabla",...rest ProdukSchema as query,foto_profil(from toko schema): "blabla"},{nama_produk: "blabla",foto_profil(from toko schema): "blabla"}
]
并对此produkSchema
进行分页(限制和偏移)
实际上,在此之前,我已经在here进行了此查询,但是该查询将产生大量数据,需要分页,
我该怎么做?我应该将produkSchema
拆分为主要子文档吗?或对此条件存在任何查询吗?
解决方法
我不确定确切的要求,但我可以猜测2个选择,
- 假设变量:
let skip = 0;
let limit = 10;
第一个选项:
- 从末尾删除
$group
个阶段,并在$unwind
个阶段之后开始 -
$replaceRoot
使用produk
合并对象foto_profil
和$mergeObjects
并替换根
{
$replaceRoot: {
newRoot: {
$mergeObjects: [{ foto_profil: "$foto_profil" },"$produk"]
}
}
},{ $skip: skip * limit },{ $limit: limit }
第二个选项:
- 从末尾删除
$group
个阶段,并在$unwind
个阶段之后开始 -
$group
(按Toko ID和Produk ID),这将对produk进行分组并获得唯一的第一个produk -
$replaceRoot
使用produk
合并对象foto_profil
和$mergeObjects
并替换根
{
$group: {
_id: {
_id: "$_id",produk_id: "$produk._id"
},root: { $first: "$$ROOT" }
}
},{
$replaceRoot: {
newRoot: {
$mergeObjects: [{ foto_profil: "$root.foto_profil" },"$root.produk"]
}
}
},{ $limit: limit }
,
也许您可以在查找后执行此操作:
- $ unwind produk(其中produk仍为数组类型,然后将其展开)。
- $ group:{_id:nama_produk等...}
- $ project ......或您想做的任何事情。
因此您可以通过nama_produk作为_id获取组列表。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。