Mongoose 查询 - groupBy 类别并获取每个类别的最后 4 项
Posted
技术标签:
【中文标题】Mongoose 查询 - groupBy 类别并获取每个类别的最后 4 项【英文标题】:Mongoose query - groupBy category and get last 4 items of each category 【发布时间】:2021-10-22 02:58:11 【问题描述】:我正在努力编写 每个类别的 4 个产品。我所做的是
exports.recentproducts = catchAsync(async (req, res, next) =>
const doc = await Product.aggregate([
$sort: date: -1 ,
$replaceRoot:
newRoot:
$mergeObjects: [ $arrayElemAt: ['$products', 0] , '$$ROOT'],
,
,
,
$group:
_id: '$productCategory',
products: $push: '$$ROOT' ,
,
,
$project:
// pagination for products
products:
$slice: ['$products', 4],
,
_id: 1,
,
,
$lookup:
from: 'Shop',
localField: 'shopId',
foreignField: '_id',
as: 'shop',
,
,
]);
文档模型
const mongoose = require('mongoose');
var ProductSchema = mongoose.Schema(
title:
type: String,
require: [true, 'Product must have a Title!'],
,
productCategory:
type: String,
require: [true, 'Product must have a Category!'],
,
shopId:
type: mongoose.Schema.ObjectId,
ref: 'Shop',
require: [true, 'Product must have a Shop!'],
,
);
var Product = mongoose.model('Product', ProductSchema);
module.exports = Product;
预期结果---
result= [
productCategory: "Graphics",
products:[//4 products object here
must populate shop data
]
,
productCategory: "3d",
products:[//4 products object here]
,
//there are seven categories I have like that
]
我所做的代码运行良好,但有两个问题 即使我尝试了查找,它也不会从 Shop 模型中填充 shopId 它不按降序对产品进行排序(不按日期排序)
【问题讨论】:
您需要向我们展示文件和预期结果 我已经添加了更多细节,请您查看 【参考方案1】:查询
在 MongoDB 5 中,我们可以使用$setWindowFields
和 $rank
按productCategory
分区并按日期降序排序
只保留rank <= 4
(4 个最新产品)
查找店铺信息
按类别分组推送产品和店铺的所有信息
Test code here
Product.aggregate(
[$setWindowFields:
partitionBy:"$productCategory",
sortBy:date:-1,
output:rank:$rank:,
$match:rank:$lte:4,
$lookup:
from:"Shop",
localField:"shopId",
foreignField:"_id",
as:"shop",
$set:shop:$first:"$shop",
$group:_id:"$productCategory", products:$push:"$$ROOT"])
【讨论】:
此代码出错。无法识别的管道阶段名称:'$setWindowFields 它需要 mongodb 5,这就是为什么我在 mongodb 5 中说我们可以这样做,我猜你有旧版本。【参考方案2】:在您实现的查询中修复了一些问题,
$sort
舞台,
$group
原样进入第二阶段
$project
原样进入第三阶段
$lookup
有店铺收藏,通过products.shopId
为localField
$project
用于合并 products
数组中的商店对象
$map
迭代 products
数组的循环
$filter
循环店铺数组返回匹配产品
$arrayElemAt
从上面的过滤结果中获取第一个元素
$mergeOjects
将当前对象与过滤后的shop
对象合并
const doc = await Product.aggregate([
$sort: date: -1 ,
$group:
_id: "$productCategory",
products: $push: "$$ROOT"
,
$project:
products: $slice: ["$products", 4]
,
$lookup:
from: "Shop",
localField: "products.shopId",
foreignField: "_id",
as: "shop"
,
$project:
products:
$map:
input: "$products",
in:
$mergeObjects: [
"$$this",
shop:
$arrayElemAt: [
$filter:
input: "$shop",
as: "s",
cond: $eq: ["$$s._id", "$$this.shopId"]
,
0
]
]
])
Playground
【讨论】:
以上是关于Mongoose 查询 - groupBy 类别并获取每个类别的最后 4 项的主要内容,如果未能解决你的问题,请参考以下文章