【发布时间】:2020-04-26 16:10:03
【问题描述】:
我是一名前端开发人员,试图在一个新的 Next 项目上扩展我的视野,第一次学习 Node、Mongo 和 GraphQL 的服务器端。 Apollo 让我印象深刻,因为我已经在之前的项目中使用过客户端 Apollo。
我一直在关注official docs,在那里我了解到apollo-datasource-mongodb(这似乎是将我的 Apollo 服务器直接插入本地 Mongo 数据库的最佳方式。不幸的是,似乎没有任何示例 repos包在行动中让我作弊,所以我只能得过且过。
我通过 mongod 在本地运行 mongo,我可以通过 mongo shell 成功执行 find() 查询,所以我知道数据库本身状况良好,包含近 600,000 条记录(我'正在处理一个相当大的数据集)。
我还可以访问位于 localhost:4000 的 Apollo Playground,因此我知道服务器正在正常启动并连接到数据库(我已经设法解决了相应的架构提示/错误)。
这是我在 Playground 中使用的查询:
{
item(id: 22298006) {
title
}
}
这是我的回复:
{
"errors": [
{
"message": "Topology is closed, please connect",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"item"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"name": "MongoError",
"stacktrace": [
"MongoError: Topology is closed, please connect",
...
]
}
}
}
],
"data": {
"item": null
}
}
我在下面附上了我的服务器文件。我怀疑这可能是某种超时错误,例如梳理所有 600k 记录以找到具有我提供的 ID 的记录需要很长时间?当我从 MongoClient 定义中删除 useUnifiedTopology: true 时,我得到一个不同的错误:
UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
但我自己没有使用异步或承诺。我在想哪一个——我应该这样吗?我可以在等待findOneById() 的返回时以某种方式暂停该过程吗(如果这确实是问题所在)?
顺便说一句,我至少看到过一个示例代码库,其中 MongoClient 在其自身中包含了一个服务器声明(也来自'mongodb' npm 包)。实现类似的东西可以让我不必在每次我想处理我的项目时都用mongod 阻塞终端窗口吗?
非常感谢您抽出宝贵时间!如果我能完成这项工作,我肯定会在 Medium 上写一篇完整的文章,或者为其他希望将 MongoClient 与 ApolloServer 配对以获得快速简单的 API 的人铺平道路。
index.js
const { MongoClient } = require('mongodb');
const assert = require('assert');
const { ApolloServer, gql } = require('apollo-server');
const { MongoDataSource } = require('apollo-datasource-mongodb');
const client = new MongoClient('mongodb://localhost:27017/projectdb', { useNewUrlParser: true, useUnifiedTopology: true }, (err) => {
err && console.log(err);
});
client.connect((err) => {
assert.equal(null, err);
client.close();
});
const db = client.db();
class Items extends MongoDataSource {
getItem(id) {
return this.findOneById(id);
}
}
const typeDefs = gql`
type Item {
id: Int!
title: String!
}
type Query {
item(id: Int!): Item
}
`;
const resolvers = {
Query: {
item: (_, { id }, { dataSources }) => dataSources.items.getItem(id),
}
}
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => ({
items: new Items(db.collection('items')),
}),
});
server.listen().then(({ url }) => {
console.log(`Server ready at ${ url }`);
});
【问题讨论】:
-
您需要在数据库操作后拥有此
client.close();。去掉那里 -
嗨@srinivasy,感谢您的回复!不幸的是,将
client.close();移动到const server = ... });和server.listen()...之间的空间仍然会导致与以前相同的错误。与将其移至文件的最后一行相同。 -
我还尝试了从
const db = client.db();到文件末尾的所有内容并将其粘贴在assert.equal(null, err);和client.close();之间,但没有运气——同样的错误。 -
这个
return this.findOneById(id);会返回什么以及id是什么? -
从
client.connect()中删除client.close();后,你能做到吗 ::async getItem(id) { let result = await this.findOneById(id); client.close(); return result; },而且这一行const client = new MongoClient()不需要回调..
标签: node.js mongodb mongoose async-await apollo-server