最小的linux服务器

Today in web development, we will be learning how to:

在Web开发的今天,我们将学习如何:

  • Easily setup a GraphQL Server with NodeJS使用NodeJS轻松设置GraphQL服务器
  • Mock data without a database using json-server使用json-server模拟没有数据库的数据
  • Build a CRUD app that speaks GraphQL构建一个讲GraphQL的CRUD应用
  • How Apollo saves us a lot of time and effort阿波罗如何为我们节省大量时间和精力

If any of these items interest you, read on! Be sure to check out the source code for this repo if you would like to refer to the completed example.

如果您对这些项目感兴趣,请继续阅读! 如果您想参考完整的示例,请确保签出此仓库的源代码 。

温柔的介绍 (Gentle Introduction)

A couple years ago, I spun up my first Node HTTP server with Express. It took only 6 lines of code on my end.

几年前,我使用Express调试了我的第一台Node HTTP服务器。 我只用了6行代码。

const express = require('express')
const app = express()app.get('/', function(req, res) { res.send({ hello: 'there' })
})app.listen(3000, () => 'Listening at http://localhost:3000')

This reduced the necessary effort for building server side apps greatly, especially considering we could use our familiar JavaScript.

这大大减少了构建服务器端应用程序所需的精力,尤其是考虑到我们可以使用我们熟悉JavaScript时。

The floodgates were opened for countless tutorials and videos on setting up a Node server, usually for building some sort of CRUD REST API in record time.

打开了闸门,以获取有关设置节点服务器的大量教程和视频,通常用于在创纪录的时间内构建某种CRUD REST API。

CRUD refers to an app, server, or backend that can create, read, update, and delete — perhaps from a real database.

CRUD是指可以创建,读取,更新和删除(可能从真实数据库中删除)的应用程序,服务器或后端。

But this is 2018, we can do much cooler things.

但这是2018年,我们可以做很多更酷的事情。

Let’s replace REST with GraphQL.

让我们用GraphQL替换REST。

输入GraphQL (Enter GraphQL)

GraphQL is a declarative data fetch and manipulation layer that makes consuming APIs more client friendly.

GraphQL是声明性的数据获取和操作层,使使用API​​的客户端更加友好。

Some benefits of consuming data via a GraphQL server are:

通过GraphQL服务器使用数据的一些好处是:

  • You get exactly the data you are requesting by specifying the fields you need.通过指定所需的字段,您可以准确获取所需的数据。
  • Fewer requests and less over-fetching. GraphQL queries are usually specific enough to avoid grabbing unnecessary records or fields.更少的请求和更少的超量获取。 GraphQL查询通常足够具体,可以避免获取不必要的记录或字段。
  • Strongly typed schemas, as opposed to raw JSON fields that have no opinion on the type of data being returned.与原始JSON字段相对的强类型模式,该原始JSON字段对返回的数据类型没有任何意见。
  • GraphQL playground for data exploration that comes with autocomplete and built-in documentation. If you like working with Postman, you would be right at home with this interface.

    带有自动完成功能和内置文档的GraphQL游乐场,用于数据探索。 如果您喜欢使用Postman ,则可以使用此界面在家中。

That last point in particular makes on-boarding new developers much easier.

最后一点尤其使新入职的开发人员更加容易。

They no longer have to study your hundreds of endpoints on swagger, because they can explore the types and relations between them in this interface.

他们不再需要研究您成百上千的端点,因为他们可以在此界面中探索它们之间的类型和关系。

More on this soon, let’s get to coding.

很快,我们开始编码。

入门和安装依赖项 (Getting Started and Installing Dependencies)

Let us start by creating a directory and initializing a package.json file.

让我们从创建目录并初始化package.json文件开始。

mkdir social-graphql && cd social-graphql && npm init -y

Our tech stack will look like this:

我们的技术堆栈将如下所示:

  • JavaScript running with Node (no client side code today)运行NodeJavaScript(今天没有客户端代码)
  • Babel for writing modern ES6通天塔写现代ES6
  • Express for quickly setting up an HTTP serverExpress,用于快速设置HTTP服务器
  • Apollo Server for all of the useful GraphQL utilities that help us set up the server and build schemasApollo Server提供所有有用的GraphQL实用程序,可帮助我们设置服务器和构建架构
  • json-server for testing on a fake dataset (much easier than querying a real database)用于在假数据集上进行测试的json服务器(比查询真实数据库要容易得多)
npm install -S express apollo-server-express graphql json-server axios

In addition, we’ll have some dev dependencies that’ll assist us.

另外,我们将有一些开发依赖关系将对我们有帮助。

npm install -D babel-cli babel-preset-env nodemon npm-run-all

With the dependencies out of the way, we can get into coding.

不用依赖,我们就可以开始编码了。

从基本的HTTP服务器开始 (Starting with a basic HTTP server)

Let’s create an HTTP server that handles the index route. That is, if I run the server and navigate to http://localhost:3500 I should see the JSON message, as opposed to ‘Cannot GET “/”’.

让我们创建一个处理索引路由的HTTP服务器。 也就是说,如果我运行服务器并导航到http:// localhost:3500 ,则应该看到JSON消息,而不是“无法获取“ /””。

Create an index.js file:

创建一个index.js文件:

import express from 'express'const PORT = process.env.PORT || 3500
const app = express()app.get('/', function(req, res) {res.send({ hello: 'there!' })
})app.listen(PORT, () => `Listening at http://localhost:${PORT}`)

This is very similar to the code at the beginning of the article, with the exception of the import syntax and the port being configurable through environment variables.

除了导入语法和可通过环境变量配置的端口外,这与本文开头的代码非常相似。

To get the import syntax working here, we’ll need to take advantage of our babel preset. Create a file called .babelrc and:

为了使导入语法在这里起作用,我们需要利用我们的babel预设。 创建一个名为.babelrc的文件,然后:

{"presets": ["env"]
}

Finally, to run the server, update the start script in package.json to this:

最后,要运行服务器,请将package.json的启动脚本更新为:

"scripts": {"dev:api": "nodemon --exec 'babel-node index.js'"
}

And then enter npm run dev:api in your terminal. By navigating to http://localhost:3500 you will be able to see a response that says “hello: there!”.

然后在终端中输入npm run dev:api 。 通过导航到http:// localhost:3500,您将看到显示“ hello:there!”的响应。

Unlike the more typical node index.js in an npm start script, we are using a dev command along with nodemon executing babel-node.

npm start脚本中更典型的node index.js不同,我们将dev命令与nodemon一起使用来执行babel-node。

Nodemon restarts your dev server whenever you save files so that you don’t have to. Usually it executes with node, but we are telling it to execute with babel-node so it handles our fancy ES6 imports.

每当您保存文件时,Nodemon都会重新启动您的开发服务器,而无需这样做。 通常它使用node执行,但是我们告诉它使用babel-node执行,因此它可以处理我们喜欢的ES6导入。

升级到阿波罗 (Upgrading to Apollo)

Alright, we have put together a basic HTTP server that can serve REST endpoints. Let us update it in order to serve GraphQL.

好的,我们已经建立了一个可以为REST端点提供服务的基本HTTP服务器。 让我们对其进行更新以服务GraphQL。

import express from 'express'
import { ApolloServer } from 'apollo-server-express'
import { resolvers, typeDefs } from './schema'const PORT = process.env.PORT || 3500
const app = express()const server = new ApolloServer({typeDefs,resolvers,playground: true
})server.applyMiddleware({ app })app.get('/', (req, res) => {res.send({ hello: 'there!' })
})app.listen(PORT, () =>console.log(`Listening at http://localhost:${PORT}/graphql`)
)

Then, inside a new file that I will call schema.js, insert:

然后,在一个我称为schema.js的新文件中,插入:

import { gql } from 'apollo-server-express'export const typeDefs = gql`type Query {users: String}
`export const resolvers = {Query: {users() {return "This will soon return users!"}}
}

解析器和架构(类型定义) (The Resolvers and Schema (type definitions))

Here, if you are new to working with GraphQL, you’ll see this funny syntax we’re assigning to typeDefs.

在这里,如果您不熟悉GraphQL,您会看到我们分配给typeDefs这个有趣的语法。

In ES6 JavaScript, we can invoke a function using backticks as we are with gql. In terms of vanilla JavaScript, you can read it like this:

在ES6 JavaScript中,我们可以像使用gql一样使用反引号来调用函数。 对于普通JavaScript,您可以这样阅读:

gql.apply(null, ["type Query {\n users: String \n }"])

Essentially, it calls gql with an array of arguments. It just so happens that writing multiline strings is convenient when expressing a JSON-like query.

本质上,它使用参数数组调用gql 。 碰巧的是,在表达类似JSON的查询时编写多行字符串很方便。

If you are still running the server, head over to http://localhost:3500/graphql. Here you’ll be able to see a fantastic interface for testing our queries.

如果仍在运行服务器,请转到http:// localhost:3500 / graphql 。 在这里,您将能够看到一个出色的界面,用于测试我们的查询。

That’s right, no more tossing cURLs at an obscure endpoint, we can test our queries with autocomplete, prettifying, and built-in documentation. It’s also out-of-the-box with Apollo, so you don’t need to install additional packages or apps.

没错,不再需要在晦涩的端点上抛出cURL了,我们可以使用自动完成,修饰和内置文档来测试查询。 它还与Apollo兼容,因此您无需安装其他软件包或应用程序。

Now, let’s make this query a little bit more interesting.

现在,让我们使该查询更有趣。

实施真实世界的GraphQL查询:列出用户 (Implementing a Real-World GraphQL Query: List Users)

Before diving too deeply into this section, be sure to copy db.json from this repository into your working directory alongside index.js and schema.js.

在深入研究本节之前,请确保将db.json从此存储库中复制到index.js和schema.js一起到您的工作目录中。

Then, update the scripts in package.json:

然后,更新package.json的脚本:

"scripts": {"dev": "npm-run-all --parallel dev:*","dev:api": "nodemon --exec 'babel-node index.js' --ignore db.json","dev:json": "json-server --watch db.json"
}

Re-run the server with npm run dev and press on.

使用npm run dev重新运行服务器,然后按。

In a GraphQL server, there is a concept of the root query. This query type is the entry point for any data fetch requests to our GraphQL schema. For us, it looks like this:

在GraphQL服务器中,存在根查询的概念。 此查询类型是对我们的GraphQL模式的任何数据获取请求的入口点。 对于我们来说,看起来像这样:

type Query {users: String
}

If we are serving users, posts, or airplanes, the client that is requesting data must do it by going through the root query.

如果我们正在为用户,职位或飞机提供服务,则请求数据的客户端必须通过根查询来完成。

type Query {users: [User] # here the "[]"s mean these are returning listsposts: [Post]airplanes: [Airplane]
}

For instance, if we wanted to define a new query on our server, we would have to update at least two places.

例如,如果要在服务器上定义一个新查询,则必须至少更新两个位置。

  1. Add the query under the Query type within our type definitions.在我们的类型定义内的“查询”类型下添加查询。
  2. Add a resolver function under the Query object in our resolvers object.在我们的resolvers对象的Query对象下添加一个resolver函数。

We would then need to make sure we have the correct type of the return data. For a lists of users, that means returning an array of objects, each with a name, email, age, friends, and ID.

然后,我们需要确保返回数据的类型正确。 对于用户列表,这意味着返回对象的数组,每个对象都有名称,电子邮件,年龄,朋友和ID。

Our current schema has our users query returning a simple string. This is no good, as we expect user data to come back from this route.

当前的模式让我们的用户查询返回一个简单的字符串。 这不好,因为我们希望用户数据会从此路由返回。

Update schema.js as follows:

如下更新schema.js

export const typeDefs = gql`type User {id: IDname: Stringage: Intemail: Stringfriends: [User]}type Query {users: [User]}
`

Great, we have the user type, and the root query that returns some list of users.

很好,我们有用户类型,还有返回一些用户列表的根查询。

Let us update the resolver:

让我们更新解析器:

export const resolvers = {Query: {users() {return userModel.list()}}
}

Inside of our resolver, we call list from the userModel, which we have yet to define.

在解析器内部,我们从尚未定义的userModel调用列表。

Inside a new file called models.js, add the following:

在名为models.js的新文件中,添加以下内容:

import axios from 'axios'class User {constructor() {this.api = axios.create({baseURL: 'http://localhost:3000' // json-server endpoint})}list() {return this.api.get('/users').then(res => res.data)}
}export default new User()

This class forms an abstraction layer over the logic that directly handles our data.

此类在直接处理我们的数据的逻辑上形成了一个抽象层。

Finally, at the top of schema.js, add this import:

最后,在schema.js的顶部,添加以下导入:

import userModel from './models'

Back to http://localhost:3500/graphql, paste and run this query:

返回http:// localhost:3500 / graphql,粘贴并运行以下查询:

query Users {users {idnameemail}
}

The user query now looks a little more exciting! For each user in our db.json file, we have returned their id, name, and email.

用户查询现在看起来更加令人兴奋! 对于db.json文件中的每个用户,我们都返回了他们的ID,名称和电子邮件。

Since we are using json-server hosted on a local port, we use the model as if it were retrieving data from a remote API.

由于我们使用的是本地端口上托管的json服务器,因此我们使用该模型,就好像它是从远程API检索数据一样。

In many cases, our model would be making database calls or retrieving data from a key-value store like firebase.

在许多情况下,我们的模型将是进行数据库调用或从诸如Firebase之类的键值存储中检索数据。

However, from the perspective of a client, they have no idea how the model is retrieving the data — they only know about the shape of the data.

但是,从客户的角度来看,他们不知道模型如何检索数据-他们只知道数据的形状。

This abstraction makes GraphQL an ideal tool for resolving data from multiple sources into a single query.

这种抽象使GraphQL成为将来自多个源的数据解析为单个查询的理想工具。

朋友之友:更激烈的查询 (Friends of Friends: A More Intense Query)

Getting a list of users is neat, and so is the GraphQL playground. But so far, you could easily do the same work with a REST endpoint.

获取用户列表很简单,GraphQL游乐场也是如此。 但是到目前为止,您可以轻松地使用REST端点执行相同的工作。

What if you wanted to retrieve the users, as well as all of the friends for a particular user? We want to run a query like this:

如果您想检索用户以及特定用户的所有朋友怎么办? 我们要运行这样的查询:

query UsersAndFriends {users {idnamefriends {idname}}
}

In order to do this, note the shape of data in our db.json file: each user has a friends field which is an array of objects keyed by ID.

为此,请注意db.json文件中的数据形状:每个用户都有一个friends字段,该字段是由ID键控的对象数组。

Basically, we are going to make some sort of request for each ID that we find, for each user.

基本上,我们将为发现的每个用户的每个ID发出某种请求。

Does it sound like an intense computation?

听起来像是一次激烈的计算吗?

It is, we would be executing a new query to our data store for every single friend of every single user we retrieve.

就是说,我们将对检索到的每个用户的每个朋友执行一个对数据库的新查询。

Implementing some sort of cache would help tremendously in reducing the amount of work done to complete the query — but let us not worry about optimizing it for now.

实现某种缓存将极大地减少完成查询所需的工作量,但现在我们不必担心对其进行优化。

In models.js, and this find method to the User class:

models.js ,该find方法用于User类:

class User {constructor() {this.api = axios.create({baseURL: 'http://localhost:3000' // json-server endpoint})}list() {return this.api.get('/users').then(res => res.data)}find(id) {return this.api.get(`/users/${id}`).then(res => res.data)}
}

Now we can use this method in a new User resolver. The difference in this resolver is that it gets used when it is trying to resolve connections to a particular type, friends here.

现在,我们可以在新的用户解析器中使用此方法。 此解析器的不同之处在于,它在尝试解析与特定类型(此处为friends连接时会使用它。

Otherwise, the query would not know how to resolve a list of Users when it sees friends.

否则,查询看到friends时将不知道如何解析用户列表。

export const resolvers = {Query: {users() {return userModel.list()}},User: {friends(source) {if (!source.friends || !source.friends.length) {return}return Promise.all(source.friends.map(({ id }) => userModel.find(id)))}},
}

In the friends method, source is the parent value that the resolver function gets called with. That is, for the user with id 0, Peck Montoya, the value of source is the whole object with the list of friend ids.

在friends方法中,source是调用解析器函数的父值。 也就是说,对于ID为0的用户Peck Montoya,source的值是带有朋友id列表的整个对象。

For root queries, source is most often undefined, because the root query is not resolved from a particular source.

对于根查询,源通常是未定义的,因为不能从特定源解析根查询。

The friends method returns when all of the requests to find individual users have been resolved.

当所有查找单个用户的请求均得到解决时,friends方法将返回。

Now try running this query if you didn’t try earlier:

如果您之前没有尝试过,现在尝试运行此查询:

query UsersAndFriends {users {idnamefriends {idname}}
}

突变:创建用户 (Mutations: Creating a User)

So far we have just been getting data. What if we wanted to mutate data?

到目前为止,我们一直在获取数据。 如果我们想突变数据怎么办?

Let’s start by creating a user with a name and age.

首先创建一个具有名称和年龄的用户。

Take a look at this mutation:

看一下这个突变:

mutation CreateUser($name: String!, $email: String, $age: Int) {createUser(name: $name, email: $email, age: $age) {nameemailage}
}

Some differences at first glance:

乍一看有些区别:

  • we denote this code with “mutation” rather than “query”我们用“变异”而不是“查询”来表示该代码
  • we pass two sets of similar looking arguments我们传递了两组相似的参数

The arguments are basically type declarations for the variables expected by our query.

参数基本上是查询所期望的变量的类型声明。

If there is a mismatch between those types and the ones passed by a client such as a web or mobile app, the GraphQL server will throw an error.

如果这些类型与客户端(如Web或移动应用程序)传递的类型不匹配,则GraphQL服务器将引发错误。

To get this query to work now, let us first update the User class in model.js:

为了使此查询立即model.js ,让我们首先更新model.js的User类:

create(data) {data.friends = data.friends ? data.friends.map(id => ({ id })) : []return this.api.post('/users', data).then(res => res.data)
}

When we fire off this request, json-server will append a new user with the data we passed up.

当我们触发此请求时,json-server将向新用户添加我们传递的数据。

Now update schema.js to the following:

现在将schema.js更新为以下内容:

export const typeDefs = gql`# other types...type Mutation {createUser(name: String!, email: String, age: Int): User}
`export const resolvers = {// other resolvers...Mutation: {createUser(source, args) {return userModel.create(args)}}
}

At this point, the query should work. But we can do a little better.

此时,查询应该可以工作了。 但是我们可以做得更好。

简化查询和变异参数 (Simplifying Query & Mutation Arguments)

Rather than write out every single argument for the mutation, we can define input types. This will make future mutations and queries we write more composable.

我们可以定义输入类型 ,而不是为突变写出每个参数。 这将使我们编写的将来的变异和查询变得更容易组合。

export const typeDefs = gql`# other types...input CreateUserInput {id: Intname: Stringage: Intemail: Stringfriends: [Int]}type Mutation {createUser(input: CreateUserInput!): User}
`export const resolvers = {// other resolvers...Mutation: {createUser(source, args) {return userModel.create(args.input)}}
}

See that if we wanted to implement an UpdateUser mutation, we could probably take advantage of this new input type.

看到如果我们想实现UpdateUser突变,我们可能可以利用这种新的输入类型。

Now try out this mutation:

现在尝试这种突变:

mutation CreateUser($input: CreateUserInput!) {createUser(input: $input) {nameemailagefriends {idname}}
}

In order to populate the variables that go into the query, click and expand the tab labeled “Query Variables“ in the lower left of the GraphQL playground.

为了填充查询中要使用的变量,请单击并展开GraphQL游乐场左下角标有“查询变量”的选项卡。

Then, input this JSON:

然后,输入以下JSON:

{"input": {"name": "Indigo Montoya","email": "indigomontoya@gmail.com","age": 29,"id": 13,"friends": [1,2]}
}

Assuming all went well, you should see a response with the user we just created. You should also see the two users with ids 1 and 2.

假设一切顺利,您应该看到我们刚刚创建的用户的响应。 您还应该看到两个ID为1和2的用户。

Now our create method isn’t totally complete — the friends of our newly created user have no idea that our new user is their friends.

现在,我们的创建方法还不够完善-我们新创建的用户的朋友并不知道我们的新用户就是他们的朋友。

In order to create a user with references to their friends, we would need to update the friends list of the users who were referenced as well.

为了创建参考他们朋友的用户,我们需要更新参考用户的朋友列表。

I will opt to leave that as an exercise to the reader if they are so inclined.

如果愿意,我选择将其留给读者练习。

连接点(包装) (Connecting the Dots (Wrapping Up))

Be sure to check out the source code for this repo if you would like to see how I implemented the deleteUser and updateUser mutations.

如果您想了解我如何实现deleteUserupdateUser突变,请务必签出此 deleteUser的源代码 。

Using GraphQL with Apollo in my own projects has been a blast. I can honestly say its just more fun to develop GraphQL schemas and resolvers than it is to implement HTTP route handlers.

在我自己的项目中将GraphQL与Apollo结合使用是一个爆炸。 老实说,开发GraphQL模式和解析器比实现HTTP路由处理程序更有趣。

If you’d like to learn more about GraphQL, check out these publications on Medium:

如果您想了解有关GraphQL的更多信息,请查看Medium中的以下出版物:

  • Open GraphQL Publication

    打开GraphQL出版物

  • Apollo Blog

    阿波罗博客

  • React Native Training

    React本地培训

If you enjoyed this article and would like to see more in the future, let me know in the comments and give me a follow on Twitter and Medium!

如果您喜欢这篇文章,并希望在以后看到更多内容,请在评论中让我知道,然后在Twitter和Medium中关注我!

翻译自: https://www.freecodecamp.org/news/learn-to-build-a-graphql-server-with-minimal-effort-fc7fcabe8ebd/

最小的linux服务器

最小的linux服务器_学习以最小的努力构建GraphQL服务器相关推荐

  1. python搭建web服务器_用Python建立最简单的web服务器

    利用Python自带的包可以建立简单的web服务器.在DOS里cd到准备做服务器根目录的路径下,输入命令:python -m Web服务器模块 [端口号,默认8000]例如:python -m Sim ...

  2. 按键精灵上传账号到服务器_学习游戏脚本制作:用按键精灵批量登录游戏账号...

    放的是账号和密码,账号和密码直接用逗号隔开,所以说,我们还需要分割一次,才能获取到账号和密码. two = split(my(1), ",") 分割之后,数组two里有两个元素,t ...

  3. azure服务器_如何使用Blazor WebAssembly实施Azure无服务器

    azure服务器 介绍 (Introduction) In this article, we will learn how to implement Azure serverless with Bla ...

  4. 国服服务器_《Minecraft我的世界》第三方服务器的基本储备

    今天我想单独来聊一聊Minecraft我的世界第三方服务器的发展. 世外荒原玩家作品 我来到头条的第一篇文章就发表了一篇我对Minecraft现状的看法,现在国服的状态对老玩家不是很友好.(这不说明国 ...

  5. gitlab设置邮件服务器_如何设置您自己的一次性电子邮件服务器

    gitlab设置邮件服务器 by Oren Geva 由Oren Geva 如何设置您自己的一次性电子邮件服务器 (How To Setup Your Own Disposable Email Ser ...

  6. 如何备份服务器日志到其他服务器_云计算迁移别忘了备份物理服务器和数据

    云已经席卷了IT世界.借助云,企业无需投资昂贵的数据中心即可获得一站式解决方案,满足其所有计算需求.云是廉价,灵活且高度可扩展的.组织正在不断虚拟化其现有工作负载,以提高云的效率.云仍在不断发展,新功 ...

  7. java做flv直播服务器_使用nginx搭建点播和直播流媒体服务器的方法步骤

    环境   centos7 nginx 1 安装nginx依赖包 yum install gcc gcc-c++ openssl-devel zlib-devel pcre pcre-devel yam ...

  8. 饥荒联机版连不上服务器_《饥荒》联机版无法连接服务器怎么办 联机版无法连接服务器解决方法...

    第1页: 展开 <饥荒>联机版的很多朋友多少都出现了无法连接服务器,今天就为大家带来了饥荒联机版无法连接服务器解决方法,教给大家怎么解决这个问题,非常实用,快跟我一起来学习下吧. 其实有时 ...

  9. ssh登录远程服务器_设置iTerm2免密登陆ssh远程服务器

    由于本人的日常工作原因,几乎所有时间都会在远程服务器工作,之前用的是Windows系统,使用xshell保存用户名和密码很方便,后来换了MacOS之后,虽然iTerm2很好用每次登陆都要自己输用户名和 ...

最新文章

  1. 【Python】纯代码通过神经网络实现线性回归的拟合
  2. 设计模式笔记——Bridge
  3. Vue-cli项目中mockjs + axios实现前后端分离代码demo(清晰易懂)
  4. 技术团队的工程师文化:效率与价值
  5. python 的输入 输出
  6. matlab knn,matlab自带knn函数
  7. 机器学习基础(二十六)—— 将 SVM 推广到多类问题
  8. C语言中类型转换那些事儿
  9. Gröbner基方法入门第II部分:Gröbner基和Buchberger算法
  10. typora+gitee图床
  11. 慕课软件工程(第五章.初始模块结构图精化的原则)
  12. 七日杀服务器直连教程,七日杀IP直连的方法
  13. 愤怒大叔-喝酒聚会游戏
  14. 织梦Dede如何删除管理员admin
  15. 【随堂笔记】数据结构基础
  16. MySQL导入Excel报1406_关于mysql 导入excel 中 数据不全或导入不了的 处理办法(工具sqlyong)借鉴经验...
  17. iview table点击单元格事件
  18. c语言求斐波那契数列n项以及前n项和
  19. C语言指针-什么是指针,如何引用指针
  20. [HNOI2006]公路修建问题 ——二分答案+krukal(蒟弱个人总结)

热门文章

  1. 抽象方法vs虚方法 c# 1613719040
  2. 编码与解码 字符串中的
  3. 草稿 图片盒子定时器模式窗口
  4. html常用标签6-表单标签
  5. Junit3.8源码--核心类
  6. 【转】微信开发出现“该公众号暂时无法提供服务,请稍后再试”的坑
  7. solr hdfs solr.in.sh
  8. 【按位dp】文盲的学习方法
  9. PHP正则判断手机号码格式/邮箱正则
  10. Several ports (8005, 8080, 8009) required by Tomcat v7.0 Server at localhost are解决方法