如何通过Node.js的MongoDB聚合按指定顺序返回数据?
解决MongoDB按选择顺序返回卡牌数据的问题
你的问题核心有两个:
find方法返回的结果默认不是$in数组的顺序,而是MongoDB的自然排序(或按索引排序)aggregate方法没返回数据,是因为输入的字符串类型和数据库中数字类型不匹配:req.body里的参数是字符串,而数据库的zahl是数字,$indexOfArray无法匹配,导致没有结果。
下面给出两种可行的解决办法:
方法一:修正Aggregate的类型匹配
把输入的字符串转成数字,同时调整投影的写法(aggregate的投影需用$project阶段),修改后的代码如下:
router.post('/cards', (req, res) => { // 将请求参数转为数字类型,匹配数据库的字段类型 let zahl1 = parseInt(req.body.zahl1); let zahl2 = parseInt(req.body.zahl2); let zahl3 = parseInt(req.body.zahl3); let zahls = [zahl1, zahl2, zahl3]; cards.aggregate([ // 匹配符合条件的卡牌 { "$match": { "zahl": { "$in": zahls } } }, // 给每条数据添加对应输入顺序的索引 { "$addFields": { "__order": { "$indexOfArray": [zahls, "$zahl"] } } }, // 按索引排序 { "$sort": { "__order": 1 } }, // 排除_id字段 { "$project": { _id: 0 } } ]).exec((err, cards) => { if (err) { return res.json({ success: false, error: err.message }); } return res.json({ success: true, cards: cards, zahls: zahls }); }); });
方法二:Find查询后在代码层排序
如果觉得aggregate逻辑复杂,也可以先用find拿到所有匹配数据,再在代码里按照输入顺序重新排列,适合数据量小的场景(比如你这里最多3张卡牌):
router.post('/cards', (req, res) => { let zahl1 = parseInt(req.body.zahl1); let zahl2 = parseInt(req.body.zahl2); let zahl3 = parseInt(req.body.zahl3); let zahls = [zahl1, zahl2, zahl3]; cards.find({ "zahl": { "$in": zahls } }, { _id: 0 }).exec((err, cards) => { if (err) { return res.json({ success: false, error: err.message }); } // 根据输入的zahls顺序,重新映射结果数组 const orderedCards = zahls.map(targetZahl => cards.find(card => card.zahl === targetZahl) ); return res.json({ success: true, cards: orderedCards, zahls: zahls }); }); });
两种方法都能实现你想要的效果:输入30、5、25时,返回的卡牌顺序和选择顺序一致。
内容的提问来源于stack exchange,提问作者kangaroo
相关产品推荐
相关产品推荐

