MongoDB聚合查询如何返回指定扁平化三品牌厂商结构JSON响应
实现方案
优先推荐简化聚合逻辑、在应用层做格式转换的方案,代码可读性更高,后续调整字段更方便,不需要写复杂的MongoDB聚合语法。
方案1:简化聚合+应用层格式转换(推荐)
调整点说明
- 移除原聚合中多余的
$group阶段:原分组逻辑不仅容易因为_id取值问题出现分组异常,还额外增加了数据嵌套层级,直接在匹配、排序、取前3条之后拿到原始文档列表即可。 - 公共字段直接从第一条返回文档提取:因为
$match阶段已经限定了generic_name/form_name/dose_size三个筛选条件,返回的3条文档这几个字段值完全一致,不需要通过聚合的$first取值。 - 遍历3条品牌数据,按顺序拼接
品牌名(厂商名)字符串,赋值给对应序号的brand_name_x字段,完成扁平化映射。
完整调整后代码
getFilterData: function (req, res, next) { console.log('Itemfilterlist getAll '); const agg = [ {'$match': { 'generic_name': req.body.generic_name, 'form_name': req.body.form_name, 'dose_size': req.body.dose_size }}, {'$sort': {'mrp': 1}}, {'$limit': 3} ] MasterModel.aggregate(agg, function (err, arrList) { if (err) { return next(err); } const filterlist = [] // 无匹配数据直接返回空列表 if (arrList && arrList.length > 0) { const baseInfo = arrList[0] const formattedRes = { id: 1, molecule: baseInfo.generic_name, form: baseInfo.form_name, strength: baseInfo.dose_size, sub_category: baseInfo.subcategory_name } // 按排序顺序拼接品牌字段 arrList.forEach((item, idx) => { formattedRes[`brand_name_${idx + 1}`] = `${item.brand_name}(${item.manufacturer_name})` }) filterlist.push(formattedRes) } res.json({ filterList: filterlist }) }); },
方案2:聚合层直接完成格式转换(不推荐)
如果需要完全在MongoDB聚合阶段完成格式映射,可以保留$group阶段,通过$concat拼接品牌和厂商字符串,再通过$replaceRoot+$arrayElemAt把数组项拆成独立字段,聚合写法如下:
const agg = [ {'$match': { 'generic_name': req.body.generic_name, 'form_name': req.body.form_name, 'dose_size': req.body.dose_size }}, {'$sort': {'mrp': 1}}, {'$limit': 3}, {'$group': { _id: null, generic_name: {$first: "$generic_name"}, form_name: {$first: "$form_name"}, dose_size: {$first: "$dose_size"}, subcategory_name: {$first: "$subcategory_name"}, brands: {$push: {$concat: ["$brand_name", "(", "$manufacturer_name", ")"]}} }}, {'$replaceRoot': { newRoot: { id: 1, molecule: "$generic_name", form: "$form_name", strength: "$dose_size", sub_category: "$subcategory_name", brand_name_1: {$arrayElemAt: ["$brands", 0]}, brand_name_2: {$arrayElemAt: ["$brands", 1]}, brand_name_3: {$arrayElemAt: ["$brands", 2]} } }} ]
注意:该方案如果匹配到的结果不足3条,对应序号的brand_name_x字段会返回null,需要额外做兼容处理。
内容的提问来源于stack exchange,提问作者bugbounter
相关产品推荐
相关产品推荐

