NodeJS,MongoDB - Return 来自 GET 请求中聚合的 JSON 响应

NodeJS,MongoDB - Return a JSON response from aggregate inside a GET request

我创建了一个聚合管道,return我的 database.I 中的许多文档也可以使用“console.log”查看结果。但我不能 return当我使用 Postman.You 时响应的结果可以使用 AreaName=Hungary,Resolution=PT15M,Year=2018,Month=1,Day=1

在 PostMan 上进行测试


var express = require('express');
var router = express.Router();
var assert = require('assert')
const URL = 'mongodb+srv://user:user@cluster0-0pwss.mongodb.net/test?retryWrites=true&w=majority'
const MongoClient = require('mongodb').MongoClient
//const CircularJSON = require('circular-json');
//const {parse, stringify} = require('flatted/cjs');



router.get('/:AreaName/:Resolution/:Year/:Month/:Day', (req, res, next) => {
  const _AreaName=req.params.AreaName
  const _Resolution=req.params.Resolution
  const _Year = parseInt(req.params.Year)
  const _Month = parseInt(req.params.Month)
  const _Day = parseInt(req.params.Day)

  MongoClient.connect(URL,{
    useNewUrlParser: true,
    useUnifiedTopology: true}, 
    async (err, client) => {
      if (err) throw err; 
      else console.log('connected to db');
      assert.equal(null, err) 
      const db = client.db('energy')
      var collection = db.collection('ActualTotalLoad')
      const agg = [
        { 
          $match : 
          {
            AreaName: _AreaName,
            Day : _Day,
            Month: _Month,
            Year: _Year
          }
      },
        
        {
          $lookup:
          {
            from: 'ResolutionCode',
            localField: 'ResolutionCodeId',
            foreignField : 'Id',
            as: "resolution_codes"
          }
        },
        {
          $unwind: {path : "$resolution_codes"}
        },

        { 
          $match : {'resolution_codes.ResolutionCodeText' : _Resolution}
        },
        {
          $addFields : {ResolutionCode : '$resolution_codes.ResolutionCodeText',
                        Source :'entso-e',
                        Dataset :'ActualTotalLoad'
        }
        },

        {
          $project : 
          {
            _id:0,
            Id : 1,
            ResolutionCodeId:1,
            Source : 1,
            AreaName: 1,
            Year : 1,
            Month : 1,
            Day : 1,
            ResolutionCode : 1
          }
        }  
      ];
      var cursor = collection.aggregate(agg)
      cursor.forEach(doc => {
        console.log(doc)
      })
    
      
     await cursor.toArray((error, result) => {
        if(error) {
            return res.status(500).send(error);
        }
        cursor.forEach(doc => {
            res.send(doc)
          })

    });

  })// connection ends here
})
module.exports = router;

-> 上面的代码给 returns 一个 json 然后服务器粉碎

我可以看到结果 " cursor.forEach(文档 => { console.log(文档)}) " 在终端中,这似乎有效 ok.What 我想问的是如何 return 在 json.Something 中做出响应,例如“ res.json(cursor) " 我尝试了一些不同的 functions/methods 来做到这一点,但 none 似乎有效。

更新 回答后我尝试了这个

cursor.toArray((error, result) => {
        if(error) {
            return res.status(500).send(error);
        }
        cursor.forEach(doc => {
            res.send(doc)
          })
    
    });

上面的代码在用 Postman returns 1 json 文档测试时 database.The 问题是它 returns 只有一个然后服务器 crashes.The 我想要 return 的文档有多个。报错信息是错误[ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are send to the client

您需要调用 .toArray() 方法来 return 所有结果。

编辑: 调试代码。将 Route 更改为 App

var express = require('express');
var app = express();

var router = express.Router();
var assert = require('assert')
const URL = 'mongodb+srv://user:user@cluster0-0pwss.mongodb.net/test?retryWrites=true&w=majority'
const MongoClient = require('mongodb').MongoClient
//const CircularJSON = require('circular-json');
//const {parse, stringify} = require('flatted/cjs');

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.get('/:AreaName/:Resolution/:Year/:Month/:Day', (req, res) => {
  const _AreaName=req.params.AreaName
  const _Resolution=req.params.Resolution
  const _Year = parseInt(req.params.Year)
  const _Month = parseInt(req.params.Month)
  const _Day = parseInt(req.params.Day)

  MongoClient.connect(URL,{
    useNewUrlParser: true,
    useUnifiedTopology: true}, 
    async (err, client) => {
      if (err) throw err; 
      else console.log('connected to db');
      assert.equal(null, err) 
      const db = client.db('energy')
      var collection = db.collection('ActualTotalLoad')
      const agg = [
        { 
          $match : 
          {
            AreaName: _AreaName,
            Day : _Day,
            Month: _Month,
            Year: _Year
          }
      },

        {
          $lookup:
          {
            from: 'ResolutionCode',
            localField: 'ResolutionCodeId',
            foreignField : 'Id',
            as: "resolution_codes"
          }
        },
        {
          $unwind: {path : "$resolution_codes"}
        },

        { 
          $match : {'resolution_codes.ResolutionCodeText' : _Resolution}
        },
        {
          $addFields : {ResolutionCode : '$resolution_codes.ResolutionCodeText',
                        Source :'entso-e',
                        Dataset :'ActualTotalLoad'
        }
        },

        {
          $project : 
          {
            _id:0,
            Id : 1,
            ResolutionCodeId:1,
            Source : 1,
            AreaName: 1,
            Year : 1,
            Month : 1,
            Day : 1,
            ResolutionCode : 1
          }
        }  
      ];
      var cursor = collection.aggregate(agg)

      await cursor.toArray((error, result) => {
        if(error) {
            return res.status(500).send(error);
        }
        res.send(result);
    });

  })// connection ends here
})
module.exports = router;

app.listen(3000, function () {
  console.log('Example app listening on port 3000!');
});

结果:

请试试这个:

/* Frameworks Used + constants */
var express = require('express');
var router = express.Router();
var assert = require('assert')
const URL = 'an Atlas MongoDB'
const MongoClient = require('mongodb').MongoClient


router.get('/base/:param1/:param2/:param3', (req, res, next) => {

    MongoClient.connect(URL, (err, client) => {
        assert.equal(null, err)
        const db = client.db('DB')
        db.collection('Collection').aggregate([{
            /* ... an aggregate with:  $lookup,$unwind,$match,$addFields,$project ..... */
        }]).toArray((err, resp) => {
            if (err) res.send({ error: err.message }); // (Or) res.status(400).end();
            if (resp.length) res.json(resp)
            res.send({ data: 'No docs found' })
        });
    })
})


module.exports = router;

(或)

/* Frameworks Used + constants */
var express = require('express');
var router = express.Router();
var assert = require('assert')
const URL = 'an Atlas MongoDB'
const MongoClient = require('mongodb').MongoClient


router.get('/base/:param1/:param2/:param3', (req, res, next) => {

    MongoClient.connect(URL, async (err, client) => {
        if(err) res.send({ error: 'DB connectivity error' });
        try {
            assert.equal(null, err)
            const db = client.db('DB')
            let resp = await db.collection('Collection').aggregate([{
                /* ... an aggregate with:  $lookup,$unwind,$match,$addFields,$project ..... */
            }]).toArray();
            if (resp.length) res.json(resp)
            res.send({ data: 'No docs found' })
        } catch (error) {
            console.error('Error ::', error)
            //res.status(400).end(); (Or)
            res.send({ error: error.message });
        }
    })
})


module.exports = router;

我之前遇到过一个非常相似的问题,它正在做的是返回承诺本身。如果它是一系列承诺,您可能想尝试这样的事情:

Promise.all(resp).then(values => res.json(values))