如何在Ubuntu 18.04上使用Node.js和MongoDB构建和部署GraphQL服务器

The author selected the Wikimedia Foundation to receive a donation as part of the Write for DOnations program.

作者选择Wikimedia Foundation接受捐赠,这是Write for DOnations计划的一部分。

介绍 (Introduction)

GraphQL was publicly released by Facebook in 2015 as a query language for APIs that makes it easy to query and mutate data from different data collections. From a single endpoint, you can query and mutate multiple data sources with a single POST request. GraphQL solves some of the common design flaws in REST API architectures, such as situations where the endpoint returns more information than you actually need. Also, it is possible when using REST APIs you would need to send requests to multiple REST endpoints to collect all the information you require—a situation that is called the n+1 problem. An example of this would be when you want to show a users’ information, but need to collect data such as personal details and addresses from different endpoints.

GraphQL是Facebook于2015年公开发布的一种API查询语言,可轻松查询和变异来自不同数据集的数据。 您可以从单个端点通过单个POST请求查询和变异多个数据源。 GraphQL解决了REST API架构中的一些常见设计缺陷,例如端点返回比您实际需要更多的信息的情况。 另外,使用REST API时,可能需要向多个REST端点发送请求以收集所需的所有信息,这种情况称为n + 1问题。 例如,当您想显示用户信息但需要从不同端点收集诸如个人详细信息和地址之类的数据时。

These problems don’t apply to GraphQL as it has only one endpoint, which can return data from multiple collections. The data it returns depends on the query that you send to this endpoint. In this query you define the structure of the data you want to receive, including any nested data collections. In addition to a query, you can also use a mutation to change data on a GraphQL server, and a subscription to watch for changes in the data. For more information about GraphQL and its concepts, you can visit the documentation on the official website.

这些问题不适用于GraphQL,因为它只有一个端点,该端点可以从多个集合返回数据。 它返回的数据取决于您发送到此端点的查询 。 在此查询中,定义要接收的数据的结构,包括任何嵌套的数据集合。 除了查询之外,您还可以使用变异来更改GraphQL服务器上的数据,以及使用订阅来监视数据中的更改。 有关GraphQL及其概念的更多信息,您可以访问官方网站上的文档

As GraphQL is a query language with a lot of flexibility, it combines especially well with document-based databases like MongoDB. Both technologies are based on hierarchical, typed schemas and are popular within the JavaScript community. Also, MongoDB’s data is stored as JSON objects, so no additional parsing is necessary on the GraphQL server.

由于GraphQL是一种具有很大灵活性的查询语言,它特别适合与基于文档的数据库(如MongoDB)结合使用 。 两种技术都基于分层的类型化模式,并且在JavaScript社区中很流行。 而且,MongoDB的数据存储为JSON对象,因此在GraphQL服务器上不需要其他解析。

In this tutorial, you’ll build and deploy a GraphQL server with Node.js that can query and mutate data from a MongoDB database that is running on Ubuntu 18.04. At the end of this tutorial, you’ll be able to access data in your database by using a single endpoint, both by sending requests to the server directly through the terminal and by using the pre-made GraphiQL playground interface. With this playground you can explore the contents of the GraphQL server by sending queries, mutations, and subscriptions. Also, you can find visual representations of the schemas that are defined for this server.

在本教程中,您将使用Node.js构建和部署GraphQL服务器,该服务器可以查询和变异在Ubuntu 18.04上运行的MongoDB数据库中的数据。 在本教程的最后,您将可以使用单个端点访问数据库中的数据,既可以通过终端直接向服务器发送请求,也可以使用预制的GraphiQL游乐场接口。 在这个游乐场中,您可以通过发送查询,变异和订阅来浏览GraphQL服务器的内容。 另外,您可以找到为此服务器定义的架构的直观表示。

At the end of this tutorial, you’ll use the GraphiQL playground to quickly interface with your GraphQL server:

在本教程的最后,您将使用GraphiQL游乐场快速连接GraphQL服务器:

先决条件 (Prerequisites)

Before you begin this guide you’ll need the following:

在开始本指南之前,您需要满足以下条件:

第1步-设置MongoDB数据库 (Step 1 — Setting Up the MongoDB Database)

Before creating the GraphQL server, make sure your database is configured right, has authentication enabled, and is filled with sample data. For this you need to connect to the Ubuntu 18.04 server running the MongoDB database from your command prompt. All steps in this tutorial will take place on this server.

在创建GraphQL服务器之前,请确保您的数据库配置正确,已启用身份验证并且已填充示例数据。 为此,您需要从命令提示符下连接到运行MongoDB数据库的Ubuntu 18.04服务器。 本教程中的所有步骤都将在此服务器上进行。

After you’ve established the connection, run the following command to check if MongoDB is active and running on your server:

建立连接后,运行以下命令以检查MongoDB是否处于活动状态并在服务器上运行:

  • sudo systemctl status mongodb

    sudo systemctl状态mongodb

You’ll see the following output in your terminal, indicating the MongoDB database is actively running:

您将在终端中看到以下输出,指示MongoDB数据库正在运行:


   
   
Output
● mongodb.service - An object/document-oriented database Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-02-23 12:23:03 UTC; 1 months 13 days ago Docs: man:mongod(1) Main PID: 2388 (mongod) Tasks: 25 (limit: 1152) CGroup: /system.slice/mongodb.service └─2388 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf

Before creating the database where you’ll store the sample data, you need to create an admin user first, since regular users are scoped to a specific database. You can do this by executing the following command that opens the MongoDB shell:

在创建用于存储示例数据的数据库之前,您需要首先创建一个admin用户,因为常规用户的作用域是特定的数据库。 您可以通过执行以下打开MongoDB Shell的命令来执行此操作:

  • mongo

    蒙哥

With the MongoDB shell you’ll get direct access to the MongoDB database and can create users or databases and query data. Inside this shell, execute the following command that will add a new admin user to MongoDB. You can replace the highlighted keywords with your own username and password combination, but don’t forget to write them down somewhere.

使用MongoDB Shell,您将可以直接访问MongoDB数据库,并且可以创建用户或数据库并查询数据。 在此Shell内,执行以下命令,该命令会将新的admin用户添加到MongoDB。 您可以用自己的用户名和密码组合替换突出显示的关键字,但不要忘记将它们写下来。

  • use admin

    使用管理员
  • db.createUser({

    db.createUser({
  • user: "admin_username",

    用户:“ admin_username ”,

  • pwd: "admin_password",

    pwd:“ admin_password ”,

  • roles: [{ role: "root", db: "admin"}]

    角色:[{角色:“ root”,数据库:“ admin”}]
  • })

    })

The first line of the preceding command selects the database called admin, which is the database where all the admin roles are stored. With the method db.createUser() you can create the actual user and define its username, password, and roles.

前面命令的第一行选择名为admin的数据库,该数据库是存储所有admin角色的数据库。 使用db.createUser()方法,您可以创建实际用户并定义其用户名,密码和角色。

Executing this command will return:

执行此命令将返回:


   
   
Output
Successfully added user: { "user" : "admin_username", "roles" : [ { "role" : "root", "db" : "admin" } ] }

You can now close the MongoDB shell by typing exit.

现在,您可以通过键入exit关闭MongoDB Shell。

Next, log in at the MongoDB shell again, but this time with the newly created admin user:

接下来,再次登录MongoDB Shell,但这一次使用新创建的admin用户登录:

  • mongo -u "admin_username" -p "admin_password" --authenticationDatabase "admin"

    mongo -u“ admin_username ” -p“ admin_password ” --authenticationDatabase“ admin”

This command will open the MongoDB shell as a specific user, where the -u flag specifies the username and the -p flag the password of that user. The extra flag --authenticationDatabase specifies that you want to log in as an admin.

此命令将以特定用户的身份打开MongoDB Shell,其中-u标志指定用户名,而-p标志指定该用户的密码。 额外的标志--authenticationDatabase指定您要以admin身份登录。

Next, you’ll switch to a new database and then use the db.createUser() method to create a new user with permissions to make changes to this database. Replace the highlighted sections with your own information, making sure to write these credentials down.

接下来,您将切换到新数据库,然后使用db.createUser()方法创建一个新用户,该用户具有对此数据库进行更改的权限。 用您自己的信息替换突出显示的部分,确保记下这些凭据。

Run the following command in the MongoDB shell:

在MongoDB Shell中运行以下命令:

  • use database_name

    使用database_name

  • db.createUser({

    db.createUser({
  • user: "username",

    用户:“ 用户名 ”,

  • pwd: "password",

    pwd:“ 密码 ”,

  • roles: ["readWrite"]

    角色:[“ readWrite”]
  • })

    })

This will return the following:

这将返回以下内容:


   
   
Output
Successfully added user: { "user" : "username", "roles" : ["readWrite"] }

After creating the database and user, fill this database with sample data that can be queried by the GraphQL server later on in this tutorial. For this, you can use the bios collection sample from the MongoDB website. By executing the commands in the following code snippet you’ll insert a smaller version of this bios collection dataset into your database. You can replace the highlighted sections with your own information, but for the purposes of this tutorial, name the collection bios:

创建数据库和用户后,用示例数据填充该数据库,本教程后面的GraphQL服务器可以查询该示例数据。 为此,您可以使用MongoDB网站上的bios收集示例。 通过执行以下代码片段中的命令,您将此bios收集数据集的较小版本插入数据库。 您可以用自己的信息替换突出显示的部分,但是出于本教程的目的,请命名collection bios

  • db.bios.insertMany([

    D b。 bios .insertMany([

  • {

    {
  • "_id" : 1,

    “ _id”:1
  • "name" : {

    “名称” : {
  • "first" : "John",

    “ first”:“ John”,
  • "last" : "Backus"

    “ last”:“ Backus”
  • },

    },
  • "birth" : ISODate("1924-12-03T05:00:00Z"),

    “出生”:ISODate(“ 1924-12-03T05:00:00Z”),
  • "death" : ISODate("2007-03-17T04:00:00Z"),

    “死亡”:ISODate(“ 2007-03-17T04:00:00Z”),
  • "contribs" : [

    “贡献”:[
  • "Fortran",

    “ Fortran”,
  • "ALGOL",

    “ ALGOL”,
  • "Backus-Naur Form",

    “巴科斯·瑙尔形式”,
  • "FP"

    “ FP”
  • ],

    ],
  • "awards" : [

    “奖项”:[
  • {

    {
  • "award" : "W.W. McDowell Award",

    “奖项”:“ WW McDowell奖”,
  • "year" : 1967,

    “年”:1967年,
  • "by" : "IEEE Computer Society"

    “ by”:“ IEEE计算机协会”
  • },

    },
  • {

    {
  • "award" : "National Medal of Science",

    “奖项”:“国家科学奖章”,
  • "year" : 1975,

    “年”:1975年,
  • "by" : "National Science Foundation"

    “ by”:“国家科学基金会”
  • },

    },
  • {

    {
  • "award" : "Turing Award",

    “奖项”:“图灵奖”,
  • "year" : 1977,

    “年”:1977年,
  • "by" : "ACM"

    “ by”:“ ACM”
  • },

    },
  • {

    {
  • "award" : "Draper Prize",

    “奖项”:“德雷珀奖”,
  • "year" : 1993,

    “年”:1993年,
  • "by" : "National Academy of Engineering"

    “ by”:“国家工程院”
  • }

    }
  • ]

    ]
  • },

    },
  • {

    {
  • "_id" : ObjectId("51df07b094c6acd67e492f41"),

    “ _id”:ObjectId(“ 51df07b094c6acd67e492f41”),
  • "name" : {

    “名称” : {
  • "first" : "John",

    “ first”:“ John”,
  • "last" : "McCarthy"

    “ last”:“ McCarthy”
  • },

    },
  • "birth" : ISODate("1927-09-04T04:00:00Z"),

    “出生”:ISODate(“ 1927-09-04T04:00:00Z”),
  • "death" : ISODate("2011-12-24T05:00:00Z"),

    “死亡”:ISODate(“ 2011-12-24T05:00:00Z”),
  • "contribs" : [

    “贡献”:[
  • "Lisp",

    “ Lisp”,
  • "Artificial Intelligence",

    “人工智能”,
  • "ALGOL"

    “ ALGOL”
  • ],

    ],
  • "awards" : [

    “奖项”:[
  • {

    {
  • "award" : "Turing Award",

    “奖项”:“图灵奖”,
  • "year" : 1971,

    “年”:1971年,
  • "by" : "ACM"

    “ by”:“ ACM”
  • },

    },
  • {

    {
  • "award" : "Kyoto Prize",

    “奖项”:“京都奖”,
  • "year" : 1988,

    “年”:1988年,
  • "by" : "Inamori Foundation"

    “ by”:“稻森基金会”
  • },

    },
  • {

    {
  • "award" : "National Medal of Science",

    “奖项”:“国家科学奖章”,
  • "year" : 1990,

    “年”:1990年,
  • "by" : "National Science Foundation"

    “ by”:“国家科学基金会”
  • }

    }
  • ]

    ]
  • }

    }
  • ]);

    ]);

This code block is an array consisting of multiple objects that contain information about successful scientists from the past. After running these commands to enter this collection into your database, you’ll receive the following message indicating the data was added:

该代码块是一个由多个对象组成的数组,其中包含有关过去成功科学家的信息。 运行这些命令以将此集合输入数据库后,您将收到以下消息,指示已添加数据:


   
   
Output
{ "acknowledged" : true, "insertedIds" : [ 1, ObjectId("51df07b094c6acd67e492f41") ] }

After seeing the success message, you can close the MongoDB shell by typing exit. Next, configure the MongoDB installation to have authorization enabled so only authenticated users can access the data. To edit the configuration of the MongoDB installation, open the file containing the settings for this installation:

看到成功消息后,您可以通过键入exit关闭MongoDB shell。 接下来,将MongoDB安装配置为启用授权,以便只有经过身份验证的用户才能访问数据。 要编辑MongoDB安装的配置,请打开包含此安装设置的文件:

  • sudo nano /etc/mongodb.conf

    须藤nano /etc/mongodb.conf

Uncomment the highlighted line in the following code to enable authorization:

在以下代码中取消注释突出显示的行以启用授权:

/etc/mongodb.conf
/etc/mongodb.conf
...
# Turn on/off security.  Off is currently the default
#noauth = true
auth = true
...

In order to make these changes active, restart MongoDB by running:

为了使这些更改生效,请通过运行以下命令重新启动MongoDB:

  • sudo systemctl restart mongodb

    sudo systemctl重新启动mongodb

Make sure the database is running again by executing the command:

通过执行以下命令,确保数据库再次运行:

  • sudo systemctl status mongodb

    sudo systemctl状态mongodb

This will yield output similar to the following:

这将产生类似于以下内容的输出:


   
   
Output
● mongodb.service - An object/document-oriented database Loaded: loaded (/lib/systemd/system/mongodb.service; enabled; vendor preset: enabled) Active: active (running) since Sat 2019-02-23 12:23:03 UTC; 1 months 13 days ago Docs: man:mongod(1) Main PID: 2388 (mongod) Tasks: 25 (limit: 1152) CGroup: /system.slice/mongodb.service └─2388 /usr/bin/mongod --unixSocketPrefix=/run/mongodb --config /etc/mongodb.conf

To make sure that your user can connect to the database you just created, try opening the MongoDB shell as an authenticated user with the command:

为了确保您的用户可以连接到刚创建的数据库,请尝试使用以下命令以经过身份验证的用户身份打开MongoDB Shell:

  • mongo -u "username" -p "password" --authenticationDatabase "database_name"

    mongo -u“ 用户名 ” -p“ 密码 ” --authenticationDatabase“ database_name ”

This uses the same flags as before, only this time the --authenticationDatabase is set to the database you’ve created and filled with the sample data.

这使用与以前相同的标志,只是这一次--authenticationDatabase设置为您创建的数据库并填充了示例数据。

Now you’ve successfully added an admin user and another user that has read/write access to the database with the sample data. Also, the database has authorization enabled meaning you need a username and password to access it. In the next step you’ll create the GraphQL server that will be connected to this database later in the tutorial.

现在,您已经成功添加了一个admin用户和另一个对具有示例数据的数据库具有读/写访问权限的用户。 另外,数据库已启用授权,这意味着您需要用户名和密码才能访问它。 在下一步中,您将创建GraphQL服务器,该服务器将在本教程的后面部分连接到该数据库。

第2步-创建GraphQL服务器 (Step 2 — Creating the GraphQL Server)

With the database configured and filled with sample data, it’s time to create a GraphQL server that can query and mutate this data. For this you’ll use Express and express-graphql, which both run on Node.js. Express is a lightweight framework to quickly create Node.js HTTP servers, and express-graphql provides middleware to make it possible to quickly build GraphQL servers.

配置好数据库并填充示例数据后,就该创建一个可以查询和修改此数据的GraphQL服务器了。 为此,您将使用Expressexpress-graphql ,它们都在Node.js上运行。 Express是一个轻量级框架,用于快速创建Node.js HTTP服务器, express-graphql提供了中间件,使快速构建GraphQL服务器成为可能。

The first step is to make sure your machine is up to date:

第一步是确保您的机器是最新的:

  • sudo apt update

    sudo apt更新

Next, install Node.js on your server by running the following commands. Together with Node.js you’ll also install npm, a package manager for JavaScript that runs on Node.js.

接下来,通过运行以下命令在服务器上安装Node.js。 与Node.js一起,您还将安装npm ,这是一个在Node.js上运行JavaScript软件包管理器。

  • sudo apt install nodejs npm

    sudo apt安装nodejs npm

After following the installation process, check if the Node.js version you’ve just installed is v8.10.0 or higher:

完成安装过程后,请检查您刚安装的Node.js版本是否为v8.10.0或更高版本:

  • node -v

    节点-v

This will return the following:

这将返回以下内容:


   
   
Output
v8.10.0

To initialize a new JavaScript project, run the following commands on the server as a sudo user, and replace the highlighted keywords with a name for your project.

要初始化新JavaScript项目,请以sudo用户的身份在服务器上运行以下命令,并将突出显示的关键字替换为项目的名称。

First move into the root directory of your server:

首先进入服务器的根目录:

  • cd

    光盘

Once there, create a new directory named after your project:

在那里,创建一个以项目命名的新目录:

  • mkdir project_name

    mkdir project_name

Move into this directory:

移至该目录:

  • cd project_name

    cd project_name

Finally, initialize a new npm package with the following command:

最后,使用以下命令初始化新的npm软件包:

  • sudo npm init -y

    须藤npm init -y

After running npm init -y you’ll receive a success message that the following package.json file was created:

运行npm init -y您将收到一条成功消息,说明已创建以下package.json文件:


   
   
Output
Wrote to /home/username/project_name/package.json: { "name": "project_name", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }

Note: You can also execute npm init without the -y flag, after which you would answer multiple questions to set up the project name, author, etc. You can enter the details or just press enter to proceed.

注意:您也可以不带-y标志而执行npm init ,此后您将回答多个问题以设置项目名称,作者等。您可以输入详细信息或按Enter继续。

Now that you’ve initialized the project, install the packages you need to set up the GraphQL server:

既然您已经初始化了项目,请安装设置GraphQL服务器所需的软件包:

  • sudo npm install --save express express-graphql graphql

    sudo npm install-保存express express-graphql graphql

Create a new file called index.js and subsequently open this file by running:

创建一个名为index.js的新文件,然后通过运行以下命令打开该文件:

  • sudo nano index.js

    须藤Nano index.js

Next, add the following code block into the newly created file to set up the GraphQL server:

接下来,将以下代码块添加到新创建的文件中以设置GraphQL服务器:

index.js
index.js
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');

// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);

// Provide resolver functions for your schema fields
const resolvers = {
  hello: () => 'Hello world!'
};

const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

This code block consists of several parts that are all important. First you describe the schema of the data that is returned by the GraphQL API:

该代码块由几个非常重要的部分组成。 首先,您描述GraphQL API返回的数据的架构:

index.js
index.js
...
// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    hello: String
  }
`);
...

The type Query defines what queries can be executed and in which format it will return the result. As you can see, the only query defined is hello that returns data in a String format.

Query类型定义可以执行哪些查询,并以哪种格式返回结果。 如您所见,定义的唯一查询是hello ,它以String格式返回数据。

The next section establishes the resolvers, where data is matched to the schemas that you can query:

下一节将建立解析器 ,其中数据与您可以查询的模式匹配:

index.js
index.js
...
// Provide resolver functions for your schema fields
const resolvers = {
  hello: () => 'Hello world!'
};
...

These resolvers are directly linked to schemas, and return the data that matches these schemas.

这些解析器直接链接到架构,并返回与这些架构匹配的数据。

The final part of this code block initializes the GraphQL server, creates the API endpoint with Express, and describes the port on which the GraphQL endpoint is running:

此代码块的最后一部分将初始化GraphQL服务器,使用Express创建API端点,并描述运行GraphQL端点的端口:

index.js
index.js
...
const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

After you have added these lines, save and exit from index.js.

添加这些行之后,保存并退出index.js

Next, to actually run the GraphQL server you need to run the file index.js with Node.js. This can be done manually from the command line, but it’s common practice to set up the package.json file to do this for you.

接下来,要实际运行GraphQL服务器,您需要使用Node.js运行文件index.js 。 这可以从命令行手动完成,但是通常的做法是设置package.json文件来为您完成此操作。

Open the package.json file:

打开package.json文件:

  • sudo nano package.json

    须藤nano package.json

Add the following highlighted line to this file:

将以下突出显示的行添加到此文件:

package.json
package.json
{
  "name": "project_name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Save and exit the file.

保存并退出文件。

To start the GraphQL server, execute the following command in the terminal:

要启动GraphQL服务器,请在终端中执行以下命令:

  • npm start

    npm开始

Once you run this, the terminal prompt will disappear, and a message will appear to confirm the GraphQL server is running:

运行此命令后,终端提示将消失,并显示一条消息以确认GraphQL服务器正在运行:


   
   
Output
🚀 Server ready at http://localhost:4000/graphql

If you now open up another terminal session, you can test if the GraphQL server is running by executing the following command. This sends a curl POST request with a JSON body after the --data flag that contains your GraphQL query to the local endpoint:

如果现在打开另一个终端会话,则可以通过执行以下命令来测试GraphQL服务器是否正在运行。 这会将包含GraphQL查询的--data标志之后的带有JSON正文的curl POST请求发送到本地端点:

  • curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ hello }" }' http://localhost:4000/graphql

    curl -X POST -H“ Content-Type:application / json” --data'{“ query”:“ {hello}”}'http:// localhost:4000 / graphql

This will execute the query as it’s described in the GraphQL schema in your code and return data in a predictable JSON format that is equal to the data as it’s returned in the resolvers:

这将按照代码中的GraphQL模式中的描述执行查询,并以可预测的JSON格式返回数据,该格式等于在解析程序中返回的数据:


   
   
Output
{ "data": { "hello": "Hello world!" } }

Note: In case the Express server crashes or gets stuck, you need to manually kill the node process that is running on the server. To kill all such processes, you can execute the following:

注意:如果Express服务器崩溃或卡住,则需要手动终止服务器上正在运行的node进程。 要终止所有此类进程,可以执行以下操作:

  • killall node

    Killall节点

After which, you can restart the GraphQL server by running:

之后,您可以通过运行以下命令重新启动GraphQL服务器:

  • npm start

    npm开始

In this step you’ve created the first version of the GraphQL server that is now running on a local endpoint that can be accessed on your server. Next, you’ll connect your resolvers to the MongoDB database.

在此步骤中,您已经创建了GraphQL服务器的第一个版本,该版本现在在可以在您的服务器上访问的本地终结点上运行。 接下来,将解析器连接到MongoDB数据库。

步骤3 —连接到MongoDB数据库 (Step 3 — Connecting to the MongoDB Database)

With the GraphQL server in order, you can now set up the connection with the MongoDB database that you configured and filled with data before and create a new schema that matches this data.

依次使用GraphQL服务器,您现在可以建立与之前配置并填充数据的MongoDB数据库的连接,并创建与该数据匹配的新架构。

To be able to connect to MongoDB from the GraphQL server, install the JavaScript package for MongoDB from npm:

为了能够从GraphQL服务器连接到MongoDB,请从npm安装用于MongoDBJavaScript软件包:

  • sudo npm install --save mongodb

    sudo npm install-保存mongodb

Once this has been installed, open up index.js in your text editor:

安装完成后,在文本编辑器中打开index.js

  • sudo nano index.js

    须藤Nano index.js

Next, add the following highlighted code to index.js just after the imported dependencies and fill the highlighted values with your own connection details to the local MongoDB database. The username, password, and database_name are those that you created in the first step of this tutorial.

接下来,在导入的依赖项之后,将以下突出显示的代码添加到index.js ,并用您自己的连接详细信息填充突出显示的值,以连接到本地MongoDB数据库。 usernamepassworddatabase_name是您在本教程的第一步中创建的username

index.js
index.js
const express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
const { MongoClient } = require('mongodb');

const context = () => MongoClient.connect('mongodb://username:password@localhost:27017/database_name', { useNewUrlParser: true }).then(client => client.db('database_name'));
...

These lines add the connection to the local MongoDB database to a function called context. This context function will be available to every resolver, which is why you use this to set up database connections.

这些行将到本地MongoDB数据库的连接添加到称为context的函数 。 每个解析器都可以使用此上下文功能,这就是为什么要使用它来建立数据库连接。

Next, in your index.js file, add the context function to the initialization of the GraphQL server by inserting the following highlighted lines:

接下来,在index.js文件中,通过插入以下突出显示的行,将上下文函数添加到GraphQL服务器的初始化中:

index.js
index.js
...
const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers,
  context
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

Now you can call this context function from your resolvers, and thereby read variables from the MongoDB database. If you look back to the first step of this tutorial, you can see which values are present in the database. From here, define a new GraphQL schema that matches this data structure. Overwrite the previous value for the constant schema with the following highlighted lines:

现在,您可以从解析器中调用此上下文函数,从而从MongoDB数据库中读取变量。 如果您回顾本教程的第一步,则可以看到数据库中存在哪些值。 在这里,定义一个与此数据结构匹配的新GraphQL模式。 用以下突出显示的行覆盖常量schema的先前值:

index.js
index.js
...
// Construct a schema, using GrahQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
  }
  type Bio {
    name: Name,
    title: String,
    birth: String,
    death: String,
    awards: [Award]
  }
  type Name {
    first: String,
    last: String
  },
  type Award {
    award: String,
    year: Float,
    by: String
  }
`);
...

The type Query has changed and now returns a collection of the new type Bio. This new type consists of several types including two other non-scalar types Name and Awards, meaning these types don’t match a predefined format like String or Float. For more information on defining GraphQL schemas you can look at the documentation for GraphQL.

Query类型已更改,现在返回新类型Bio的集合。 此新类型由几种类型组成,包括另外两个非标量类型NameAwards ,这意味着这些类型与StringFloat类的预定义格式不匹配。 有关定义GraphQL模式的更多信息,请查看GraphQL的文档

Also, since the resolvers tie the data from the database to the schema, update the code for the resolvers when you make changes to the schema. Create a new resolver that is called bios, which is equal to the Query that can be found in the schema and the name of the collection in the database. Note that, in this case, the name of the collection in db.collection('bios') is bios, but that this would change if you had assigned a different name to your collection.

另外,由于解析程序会将数据库中的数据绑定到架构,因此在更改架构时更新解析程序的代码。 创建一个名为bios的新解析器,该解析器等于可以在模式中找到的Query和数据库中集合的名称。 请注意,在这种情况下, db.collection('bios')中的集合名称为bios ,但是如果您为集合指定了其他名称,则该名称将会更改。

Add the following highlighted line to index.js:

将以下突出显示的行添加到index.js

index.js
index.js
...
// Provide resolver functions for your schema fields
const resolvers = {
  bios: (args, context) => context().then(db => db.collection('bios').find().toArray())
};
...

This function will use the context function, which you can use to retrieve variables from the MongoDB database. Once you have made these changes to the code, save and exit index.js.

此函数将使用上下文函数,您可以使用上下文函数从MongoDB数据库中检索变量。 对代码进行这些更改后,保存并退出index.js

In order to make these changes active, you need to restart the GraphQL server. You can stop the current process by using the keyboard combination CTRL + C and start the GraphQL server by running:

为了使这些更改生效,您需要重新启动GraphQL服务器。 您可以使用组合键CTRL + C停止当前进程,并通过运行以下命令启动GraphQL服务器:

  • npm start

    npm开始

Now you’re able to use the updated schema and query the data that is inside the database. If you look at the schema, you’ll see that the Query for bios returns the type Bio; this type could also return the type Name.

现在,您可以使用更新的架构并查询数据库中的数据。 如果查看模式,您将看到Query for bios返回类型Bio ; 此类型还可以返回Name类型。

To return all the first and last names for all the bios in the database, send the following request to the GraphQL server in a new terminal window:

要返回数据库中所有BIOS的所有名字和姓氏,请将以下请求发送到新终端窗口中的GraphQL服务器:

  • curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bios { name { first, last } } }" }' http://localhost:4000/graphql

    curl -X POST -H“ Content-Type:application / json” --data'{“ query”:“ {bios {名称{first,last}}}”}}'http:// localhost:4000 / graphql

This again will return a JSON object that matches the structure of the schema:

这将再次返回与模式结构匹配的JSON对象:


   
   
Output
{"data":{"bios":[{"name":{"first":"John","last":"Backus"}},{"name":{"first":"John","last":"McCarthy"}}]}}

You can easily retrieve more variables from the bios by extending the query with any of the types that are described in the type for Bio.

通过将查询扩展为Bio类型中描述的任何类型,可以轻松地从bios中检索更多变量。

Also, you can retrieve a bio by specifying an id. In order to do this you need to add another type to the Query type and extend the resolvers. To do this, open index.js in your text editor:

另外,您可以通过指定id来检索简历。 为此,您需要向Query类型添加另一种类型并扩展解析器。 为此,请在文本编辑器中打开index.js

  • sudo nano index.js

    须藤Nano index.js

Add the following highlighted lines of code:

添加以下突出显示的代码行:

index.js
index.js
...
// Construct a schema, using GrahQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
    bio(id: Int): Bio
  }

  ...

  // Provide resolver functions for your schema fields
  const resolvers = {
    bios: (args, context) => context().then(db => db.collection('bios').find().toArray()),
    bio: (args, context) => context().then(db => db.collection('bios').findOne({ _id: args.id }))
  };
  ...

Save and exit the file.

保存并退出文件。

In the terminal that is running your GraphQL server, press CTRL + C to stop it from running, then execute the following to restart it:

在运行GraphQL服务器的终端中,按CTRL + C使其停止运行,然后执行以下命令将其重新启动:

  • npm start

    npm开始

In another terminal window, execute the following GraphQL request:

在另一个终端窗口中,执行以下GraphQL请求:

  • curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bio(id: 1) { name { first, last } } }" }' http://localhost:4000/graphql

    curl -X POST -H“ Content-Type:application / json” --data'{“ query”:“ {bio(id:1){名称{first,last}}}”}'http:// localhost: 4000 / graphql

This returns the entry for the bio that has an id equal to 1:

这将返回id等于1的生物的条目:


   
   
Output
{ "data": { "bio": { "name": { "first": "John", "last": "Backus" } } } }

Being able to query data from a database is not the only feature of GraphQL; you can also change the data in the database. To do this, open up index.js:

能够从数据库查询数据并不是GraphQL的唯一功能; 您还可以更改数据库中的数据。 为此,请打开index.js

  • sudo nano index.js

    须藤Nano index.js

Next to the type Query you can also use the type Mutation, which allows you to mutate the database. To use this type, add it to the schema and also create input types by inserting these highlighted lines:

Query类型旁边,您还可以使用类型Mutation ,它允许您对数据库进行突变。 要使用此类型,请将其添加到架构,并通过插入以下突出显示的行来创建输入类型:

index.js
index.js
...
// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
    bio(id: Int): Bio
  }
  type Mutation {
    addBio(input: BioInput) : Bio
  }
  input BioInput {
    name: NameInput
    title: String
    birth: String
    death: String
  }
  input NameInput {
    first: String
    last: String
  }
...

These input types define which variables can be used as inputs, which you can access in the resolvers and use to insert a new document in the database. Do this by adding the following lines to index.js:

这些输入类型定义了哪些变量可用作输入,您可以在解析器中访问这些变量,并用于在数据库中插入新文档。 为此,请在index.js添加以下几行:

index.js
index.js
...
// Provide resolver functions for your schema fields
const resolvers = {
  bios: (args, context) => context().then(db => db.collection('bios').find().toArray()),
  bio: (args, context) => context().then(db => db.collection('bios').findOne({ _id: args.id })),
  addBio: (args, context) => context().then(db => db.collection('bios').insertOne({ name: args.input.name, title: args.input.title, death: args.input.death, birth: args.input.birth})).then(response => response.ops[0])
};
...

Just as with the resolvers for regular queries, you need to return a value from the resolver in index.js. In the case of a Mutation where the type Bio is mutated, you would return the value of the mutated bio.

与常规查询的解析器一样,您需要在index.js从解析器返回一个值。 如果是Bio类型发生突变的Mutation ,则将返回突变的bio的值。

At this point, your index.js file will contain the following lines:

此时,您的index.js文件将包含以下几行:

index.js
index.js
iconst express = require('express');
const graphqlHTTP = require('express-graphql');
const { buildSchema } = require('graphql');
const { MongoClient } = require('mongodb');

const context = () => MongoClient.connect('mongodb://username:password@localhost:27017/database_name', { useNewUrlParser: true })
  .then(client => client.db('GraphQL_Test'));

// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    bios: [Bio]
    bio(id: Int): Bio
  }
  type Mutation {
    addBio(input: BioInput) : Bio
  }
  input BioInput {
    name: NameInput
    title: String
    birth: String
    death: String
  }
  input NameInput {
    first: String
    last: String
  }
  type Bio {
    name: Name,
    title: String,
    birth: String,
    death: String,
    awards: [Award]
  }
  type Name {
    first: String,
    last: String
  },
  type Award {
    award: String,
    year: Float,
    by: String
  }
`);

// Provide resolver functions for your schema fields
const resolvers = {
  bios: (args, context) =>context().then(db => db.collection('Sample_Data').find().toArray()),
  bio: (args, context) =>context().then(db => db.collection('Sample_Data').findOne({ _id: args.id })),
  addBio: (args, context) => context().then(db => db.collection('Sample_Data').insertOne({ name: args.input.name, title: args.input.title, death: args.input.death, birth: args.input.birth})).then(response => response.ops[0])
};

const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers,
  context
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

Save and exit index.js.

保存并退出index.js

To check if your new mutation is working, restart the GraphQL server by pressing CTRL + c and running npm start in the terminal that is running your GraphQL server, then open another terminal session to execute the following curl request. Just as with the curl request for queries, the body in the --data flag will be sent to the GraphQL server. The highlighted parts will be added to the database:

要检查您的新突变是否有效,请按CTRL + c并在运行GraphQL服务器的终端中运行npm start GraphQL服务器,然后打开另一个终端会话以执行以下curl请求。 就像对curl的查询请求一样,-- --data标志中的主体将发送到GraphQL服务器。 突出显示的部分将添加到数据库中:

  • curl -X POST -H "Content-Type: application/json" --data '{ "query": "mutation { addBio(input: { name: { first: \"test\", last: \"user\" } }) { name { first, last } } }" }' http://localhost:4000/graphql

    curl -X POST -H“ Content-Type:application / json” --data'{“ query”:“变异{addBio(input:{name:{first:\” test \“,last:\” user \“ }}} {名称{first,last}}}“}'http:// localhost:4000 / graphql

This returns the following result, meaning you just inserted a new bio to the database:

这将返回以下结果,这意味着您刚刚向数据库中插入了新的履历:


   
   
Output
{ "data": { "addBio": { "name": { "first": "test", "last": "user" } } } }

In this step, you created the connection with MongoDB and the GraphQL server, allowing you to retrieve and mutate data from this database by executing GraphQL queries. Next, you’ll expose this GraphQL server for remote access.

在此步骤中,您创建了与MongoDB和GraphQL服务器的连接,从而允许您通过执行GraphQL查询从该数据库检索和变异数据。 接下来,您将公开此GraphQL服务器以进行远程访问。

步骤4 —允许远程访问 (Step 4 — Allowing Remote Access)

Having set up the database and the GraphQL server, you can now configure the GraphQL server to allow remote access. For this you’ll use Nginx, which you set up in the prerequisite tutorial How to install Nginx on Ubuntu 18.04. This Nginx configuration can be found in the /etc/nginx/sites-available/example.com file, where example.com is the server name you added in the prerequisite tutorial.

设置数据库和GraphQL服务器后,您现在可以配置GraphQL服务器以允许远程访问。 为此,您将使用Nginx,它是在先决条件教程“ 如何在Ubuntu 18.04上安装Nginx”中设置的 。 您可以在/etc/nginx/sites-available/ example.com文件中找到此Nginx配置,其中example.com是您在先决条件教程中添加的服务器名称。

Open this file for editing, replacing your domain name with example.com:

打开此文件进行编辑,将您的域名替换为example.com

  • sudo nano /etc/nginx/sites-available/example.com

    须藤纳米/ etc / nginx / sites-available / example.com

In this file you can find a server block that listens to port 80, where you’ve already set up a value for server_name in the prerequisite tutorial. Inside this server block, change the value for root to be the directory in which you created the code for the GraphQL server and add index.js as the index. Also, within the location block, set a proxy_pass so you can use your server’s IP or a custom domain name to refer to the GraphQL server:

在此文件中,您可以找到一个侦听端口80的服务器块,您已在前提条件教程中为server_name设置了一个值。 在此服务器块内,将root的值更改为在其中创建GraphQL服务器代码的目录,并添加index.js作为索引。 另外,在位置块中,设置proxy_pass以便您可以使用服务器的IP或自定义域名来引用GraphQL服务器:

/etc/nginx/sites-available/example.com
/etc/nginx/sites-available/example.com
server {
  listen 80;
  listen [::]:80;

  root /project_name;
  index index.js;

  server_name example.com;

  location / {
    proxy_pass http://localhost:4000/graphql;
  }
}

Make sure there are no Nginx syntax errors in this configuration file by running:

通过运行以下命令,确保此配置文件中没有Nginx语法错误:

  • sudo nginx -t

    须藤Nginx -t

You will receive the following output:

您将收到以下输出:


   
   
Output
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful

When there are no errors found for the configuration file, restart Nginx:

如果没有发现配置文件错误,请重新启动Nginx:

  • sudo systemctl restart nginx

    sudo systemctl重启nginx

Now you will be able to access your GraphQL server from any terminal session tab by executing and replacing example.com by either your server’s IP or your custom domain name:

现在,您可以通过使用服务器的IP或自定义域名执行并替换example.com ,从任何终端会话选项卡中访问GraphQL服务器:

  • curl -X POST -H "Content-Type: application/json" --data '{ "query": "{ bios { name { first, last } } }" }' http://example.com

    curl -X POST -H“ Content-Type:application / json” --data'{“ query”:“ {bios {名称{first,last}}}”}}'http:// example.com

This will return the same JSON object as the one of the previous step, including any additional data you might have added by using a mutation:

这将返回与上一步相同的JSON对象,包括您可能通过使用突变添加的所有其他数据:


   
   
Output
{"data":{"bios":[{"name":{"first":"John","last":"Backus"}},{"name":{"first":"John","last":"McCarthy"}},{"name":{"first":"test","last":"user"}}]}}

Now that you have made your GraphQL server accessible remotely, make sure your GraphQL server doesn’t go down when you close the terminal or the server restarts. This way, your MongoDB database will be accessible via the GraphQL server whenever you want to make a request.

既然您已使GraphQL服务器可以远程访问,请确保在关闭终端或服务器重新启动时GraphQL服务器不会关闭。 这样,无论何时您要发出请求,MongoDB数据库都可以通过GraphQL服务器进行访问。

To do this, use the npm package forever, a CLI tool that ensures that your command line scripts run continuously, or get restarted in case of any failure.

为此,请forever使用npm软件包,这是一个CLI工具,可确保您的命令行脚本连续运行,或者在发生任何故障时重新启动。

Install forever with npm:

使用npm forever安装:

  • sudo npm install forever -g

    sudo npm永久安装-g

Once it is done installing, add it to the package.json file:

安装完成后,将其添加到package.json文件:

package.json
package.json
{
  "name": "project_name",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "deploy": "forever start --minUptime 2000 --spinSleepTime 5 index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  ...

To start the GraphQL server with forever enabled, run the following command:

forever启用GraphQL服务器,请运行以下命令:

  • npm run deploy

    npm运行部署

This will start the index.js file containing the GraphQL server with forever, and ensure it will keep running with a minimum uptime of 2000 milliseconds and 5 milliseconds between every restart in case of a failure. The GraphQL server will now continuously run in the background, so you don’t need to open a new tab any longer when you want to send a request to the server.

这将启动index.js包含与GraphQL服务器文件forever ,并确保它会保持与2000毫秒以及每次重新启动之间5毫秒的故障的情况下的最小运行时间运行。 GraphQL服务器现在将在后台连续运行,因此,当您要将请求发送到服务器时,不再需要打开新选项卡。

You’ve now created a GraphQL server that is using MongoDB to store data and is set up to allow access from a remote server. In the next step you’ll enable the GraphiQL playground, which will make it easier for you to inspect the GraphQL server.

现在,您已经创建了一个使用MongoDB来存储数据的GraphQL服务器,并将其设置为允许从远程服务器进行访问。 在下一步中,您将启用GraphiQL游乐场,这将使您更轻松地检查GraphQL服务器。

步骤5 —启用GraphiQL游乐场 (Step 5 — Enabling GraphiQL Playground)

Being able to send cURL requests to the GraphQL server is great, but it would be faster to have a user interface that can execute GraphQL requests immediately, especially during development. For this you can use GraphiQL, an interface supported by the package express-graphql.

能够将cURL请求发送到GraphQL服务器很棒,但是拥有一个可以立即执行GraphQL请求的用户界面会更快,尤其是在开发过程中。 为此,您可以使用GraphiQL,这是包express-graphql支持的接口。

To enable GraphiQL, edit the file index.js:

要启用GraphiQL,请编辑文件index.js

  • sudo nano index.js

    须藤Nano index.js

Add the following highlighted lines:

添加以下突出显示的行:

index.js
index.js
const app = express();
app.use('/graphql', graphqlHTTP({
  schema,
  rootValue: resolvers,
  context,
  graphiql: true
}));
app.listen(4000);

console.log(`🚀 Server ready at http://localhost:4000/graphql`);

Save and exit the file.

保存并退出文件。

In order for these changes to become visible, make sure to stop forever by executing:

为了使这些更改可见,请确保通过执行以下操作forever停止:

  • forever stop index.js

    永远停止index.js

Next, start forever again so the latest version of your GraphQL server is running:

接下来, forever重新启动,以便最新版本的GraphQL服务器正在运行:

  • npm run deploy

    npm运行部署

Open a browser at the URL http://example.com, replacing example.com with your domain name or your server IP. You will see the GraphiQL playground, where you can type GraphQL requests.

在URL http:// example.com打开浏览器,用您的域名或服务器IP替换example.com 。 您将看到GraphiQL游乐场,您可以在其中键入GraphQL请求。

On the left side of this playground you can type the GraphQL queries and mutations, while the output will be shown on the right side of the playground. To test if this is working, type the following query on the left side:

在此操场的左侧,您可以键入GraphQL查询和变异,而输出将显示在操场的右侧。 要测试是否有效,请在左侧键入以下查询:

query {
  bios {
    name {
      first
      last
    }
  }
}

This will output the same result on the right side of the playground, again in JSON format:

这将在操场的右侧以JSON格式再次输出相同的结果:

Now you can send GraphQL requests using the terminal and the GraphiQL playground.

现在,您可以使用终端和GraphiQL游乐场发送GraphQL请求。

结论 (Conclusion)

In this tutorial you’ve set up a MongoDB database and retrieved and mutated data from this database using GraphQL, Node.js, and Express for the server. Additionally, you configured Nginx to allow remote access to this server. Not only can you send requests to this GraphQL server directly, you can also use the GraphiQL as a visual, in-browser GraphQL interface.

在本教程中,您将建立一个MongoDB数据库,并使用GraphQL,Node.js和Express作为服务器从该数据库中检索和变异数据。 此外,您还配置了Nginx以允许对该服务器的远程访问。 您不仅可以直接将请求发送到此GraphQL服务器,还可以将GraphiQL用作可视的浏览器内GraphQL界面。

If you want to learn about GraphQL, you can watch a recording of my presentation on GraphQL at NDC {London} or visit the website howtographql.com for tutorials about GraphQL. To study how GraphQL interacts with other technologies, check out the tutorial on How to Manually Set Up a Prisma Server on Ubuntu 18.04, and for more information on building applications with MongoDB, see How To Build a Blog with Nest.js, MongoDB, and Vue.js.

如果您想了解GraphQL,可以在NDC {伦敦}上观看我在GraphQL上的演示文稿的录音 ,或者访问网站howtographql.com上有关GraphQL的教程。 要研究GraphQL如何与其他技术交互,请查看有关如何在Ubuntu 18.04上手动设置Prisma服务器的教程,有关使用MongoDB构建应用程序的更多信息,请参见如何使用Nest.js,MongoDB和构建博客。 Vue.js。

翻译自: https://www.digitalocean.com/community/tutorials/how-to-build-and-deploy-a-graphql-server-with-node-js-and-mongodb-on-ubuntu-18-04

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值