MongoError:拓扑已关闭,请连接

时间:2020-01-09 04:54:20

标签: node.js mongodb mongoose async-await apollo-server

我是一名前端开发人员,试图在新的Next项目上拓展视野,第一次学习Node,Mongo和GraphQL的服务器端。 Apollo吸引了我,因为我已经在以前的项目中使用过客户端Apollo。

我一直在跟踪official docs,在那里我了解到apollo-datasource-mongodb(似乎是将Apollo Server直接插入本地Mongo数据库的最佳方法。不幸的是,似乎没有任何方法这个程序包的示例存储库让我作弊,所以我不得不去摸索。

我的mongo通过mongod在本地运行,并且可以通过mongo shell成功执行find()查询,因此我知道数据库本身状态良好,并且包含近 600,000条记录(我正在处理相当大的数据集)。

我还可以访问localhost:4000处的Apollo游乐场,因此我知道服务器正在正常启动并连接到数据库(带有自此以来一直设法解决的适当的架构提示/错误)。

这是我在操场上使用的查询:

{
  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本身包含了一个Server声明(也来自'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 }`);
});

2 个答案:

答案 0 :(得分:1)

由于GitHub在apollo-datasource-mongodb上的“ Used By”下拉列表,我能够欺骗其他一些存储库,而这就是我最终的结果(在注释中标记了更改):

# Leave all the user input the same except you don't need to input day  for month range query
month_start = datetime.date(year, month, 1)
next_month_start = datetime.date(year, (month + 1) % 12, 1)
c.execute('SELECT CategoryID, AmountSpent from tblFinance WHERE FinanceDate BETWEEN ? AND ?', (month_start, next_month_start))

有了这些更改,位于localhost:4000的Apollo Playground很棒!现在要解决400错误,当我查询时我进入客户端应用程序...

答案 1 :(得分:1)

实际上,还有另一件事可能导致此问题,因为我也有相同的确切错误“拓扑已关闭,请连接”。

问题是,如果您具有动态IP地址,那么在MongoDB地图集中,您应该尝试允许所有IP地址。

添加IP地址:0.0.0.0/0 将这个IP地址列入白名单后,我所有的问题都解决了。

动态IP 0.0.0.0/0的图像:

enter image description here