Nodejs 关于如何按条件分组查询,并返回结构

Nodejs 关于如何按条件分组查询,并返回结构

需求如下: 现有History的Model有三个字段 :Content,Year,Month 数据: 1 “aaa”,2013,12 2 “bbb”,2013,11 3 “ccc”,2012,12 4 “ddd”,2011,03

想将数据按照Year来分组,保存到数组中,最后通过,res.render到具体页面 [{“aaa”,2013,} {“bbb”,2013,11}], [{“ccc”,2012,12}], [{“ddd”,2011,03}],

我的代码如下: index.js: var hisArrs=[]; History.distinct(“Year”,function(err,doc){ var years=doc; years.forEach(function(year){ History.find({“Year”:year},function(err,docs){ hisArrs.push(docs); }); }) ;
});

res.render(‘History/history’,{ title:‘history’, HisArrs:hisArrs }); 我代码思路大概是这样的,代码执行结果是不对的,请问应该怎样解决我的问题啊


4 回复

为了实现你的需求,即按照 Year 字段对数据进行分组,并将结果传递给前端页面,我们需要使用 MongoDB 的聚合框架(Aggregation Framework)。以下是一个更简洁且有效的解决方案。

解决方案

首先,你需要确保你已经安装了 mongoose 库,它可以帮助我们更好地操作 MongoDB 数据库。如果你还没有安装,可以通过以下命令安装:

npm install mongoose

接下来,我们修改 index.js 文件,使用 MongoDB 的聚合管道来实现数据分组。

修改后的 index.js 文件

const express = require('express');
const mongoose = require('mongoose');

// 连接到数据库
mongoose.connect('mongodb://localhost/mydatabase', { useNewUrlParser: true, useUnifiedTopology: true });

const History = mongoose.model('History', new mongoose.Schema({
    Content: String,
    Year: Number,
    Month: Number
}));

const app = express();

app.get('/histories', async (req, res) => {
    try {
        const result = await History.aggregate([
            {
                $group: {
                    _id: "$Year",
                    histories: { $push: { Content: "$Content", Year: "$Year", Month: "$Month" } }
                }
            },
            {
                $project: {
                    _id: 0,
                    year: "$_id",
                    histories: 1
                }
            }
        ]);

        res.render('History/history', {
            title: 'history',
            HisArrs: result
        });
    } catch (error) {
        console.error(error);
        res.status(500).send('Server Error');
    }
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. 连接数据库:我们首先连接到 MongoDB 数据库。
  2. 定义模型:定义 History 模型,用于映射数据库中的集合。
  3. 路由处理:定义一个 GET 路由 /histories,在这个路由中,我们使用 History.aggregate 方法来执行聚合操作。
  4. 聚合管道
    • $group 阶段:根据 Year 字段进行分组,并将每个文档推入一个数组中。
    • $project 阶段:重新格式化输出,去掉 _id 字段,保留 Yearhistories 字段。
  5. 渲染视图:将分组后的数据传递给前端页面。

这样,你就可以得到按年份分组的数据,并将其传递给前端页面。希望这能帮助你解决问题!


求解答啊,有木有遇到过啊。。。。。。

自己解决咯,哈哈哈

根据你的需求,你需要按 Year 字段对数据进行分组,并将结果传递给前端页面。你当前的代码存在一些问题,例如异步操作没有正确处理。下面是一个改进后的解决方案:

解决方案

你可以使用 async/await 来更好地管理异步操作,并使用 lodash 库来帮助处理分组逻辑。

示例代码

const async = require('async');
const _ = require('lodash');

// 使用 async/await 管理异步操作
app.get('/history', async (req, res) => {
    try {
        // 获取所有年份并去重
        const years = await History.distinct('Year');
        
        // 创建一个空对象用于存储分组后的数据
        let groupedData = {};
        
        // 遍历每一年的数据并进行分组
        for (let year of years) {
            let docs = await History.find({ Year: year });
            groupedData[year] = docs.map(doc => ({ Content: doc.Content, Month: doc.Month }));
        }
        
        // 将分组后的数据转换为数组格式
        let result = Object.values(groupedData);

        res.render('History/history', {
            title: 'history',
            HisArrs: result
        });
    } catch (err) {
        console.error(err);
        res.status(500).send('Server error');
    }
});

解释

  1. 引入依赖:引入 asynclodash 库。
  2. 获取年份:使用 distinct 方法获取所有不同的年份。
  3. 创建分组对象:使用一个对象 groupedData 来存储每个年份对应的数据。
  4. 遍历年份并查询数据:使用 for...of 循环遍历每一年的数据,并调用 find 方法获取该年份的所有记录。
  5. 映射记录:将查询结果中的 ContentMonth 映射到新的对象中。
  6. 转换为数组:将 groupedData 对象的值转换为数组,并将其传递给 res.render 方法。

这样可以确保异步操作按顺序执行,并且能够正确地将数据传递给前端页面。

回到顶部