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))
我创建了一个聚合管道,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))