feat: add 'back/front end' in curriculum (#42596)
* chore: rename APIs and Microservices to include "Backend" (#42515) * fix typo * fix typo * undo change * Corrected grammar mistake Corrected a grammar mistake by removing a comma. * change APIs and Microservices cert title * update title * Change APIs and Microservices certi title * Update translations.json * update title * feat(curriculum): rename apis and microservices cert * rename folder structure * rename certificate * rename learn Markdown * apis-and-microservices -> back-end-development-and-apis * update backend meta * update i18n langs and cypress test Co-authored-by: Shaun Hamilton <shauhami020@gmail.com> * fix: add development to front-end libraries (#42512) * fix: added-the-word-Development-to-front-end-libraries * fix/added-the-word-Development-to-front-end-libraries * fix/added-word-development-to-front-end-libraries-in-other-related-files * fix/added-the-word-Development-to-front-end-and-all-related-files * fix/removed-typos-from-last-commit-in-index.md * fix/reverted-changes-that-i-made-to-dependecies * fix/removed xvfg * fix/reverted changes that i made to package.json * remove unwanted changes * front-end-development-libraries changes * rename backend certSlug and README * update i18n folder names and keys * test: add legacy path redirect tests This uses serve.json from the client-config repo, since we currently use that in production * fix: create public dir before moving serve.json * fix: add missing script * refactor: collect redirect tests * test: convert to cy.location for stricter tests * rename certificate folder to 00-certificates * change crowdin config to recognise new certificates location * allow translations to be used Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com> * add forwards slashes to path redirects * fix cypress path tests again * plese cypress * fix: test different challenge Okay so I literally have no idea why this one particular challenge fails in Cypress Firefox ONLY. Tom and I paired and spun a full build instance and confirmed in Firefox the page loads and redirects as expected. Changing to another bootstrap challenge passes Cypress firefox locally. Absolutely boggled by this. AAAAAAAAAAAAAAA * fix: separate the test Okay apparently the test does not work unless we separate it into a different `it` statement. >:( >:( >:( >:( Co-authored-by: Sujal Gupta <55016909+heysujal@users.noreply.github.com> Co-authored-by: Noor Fakhry <65724923+NoorFakhry@users.noreply.github.com> Co-authored-by: Oliver Eyton-Williams <ojeytonwilliams@gmail.com> Co-authored-by: Nicholas Carrigan (he/him) <nhcarrigan@gmail.com>
This commit is contained in:
@ -0,0 +1,76 @@
|
||||
---
|
||||
id: 587d7fb9367417b2b2512c12
|
||||
title: 通过链式调用辅助查询函数来缩小搜索结果
|
||||
challengeType: 2
|
||||
forumTopicId: 301533
|
||||
dashedName: chain-search-query-helpers-to-narrow-search-results
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
如果不给 `Model.find()`(或者别的搜索方法)的最后一个参数传入回调函数, 查询将不会执行。 可以将查询条件存储在变量中供以后使用, 也可以通过链式调用这类变量来构建新的查询字段。 实际的数据库操作会在最后调用 `.exec()` 方法时执行。 必须把回调函数传给最后一个方法。 Mongoose 提供了许多辅助查询函数, 这里使用最常见的一种。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `queryChain` 函数来查询喜欢 `foodToSearch` 食物的人。 同时,需要将查询结果按 `name` 属性排序, 查询结果应限制在两个 document 内,并隐藏 age 属性。 请链式调用 `.find()`、`.sort()`、`.limit()` 和 `.select()`,并在最后调用 `.exec()`, 并将 `done(err, data)` 回调函数传入 `exec()`。
|
||||
|
||||
# --hints--
|
||||
|
||||
应该成功地链式调用辅助查询函数。
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.ajax({
|
||||
url: getUserInput('url') + '/_api/query-tools',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify([
|
||||
{ name: 'Pablo', age: 26, favoriteFoods: ['burrito', 'hot-dog'] },
|
||||
{ name: 'Bob', age: 23, favoriteFoods: ['pizza', 'nachos'] },
|
||||
{ name: 'Ashley', age: 32, favoriteFoods: ['steak', 'burrito'] },
|
||||
{ name: 'Mario', age: 51, favoriteFoods: ['burrito', 'prosciutto'] }
|
||||
])
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.isArray(data, 'the response should be an Array');
|
||||
assert.equal(
|
||||
data.length,
|
||||
2,
|
||||
'the data array length is not what expected'
|
||||
);
|
||||
assert.notProperty(
|
||||
data[0],
|
||||
'age',
|
||||
'The returned first item has too many properties'
|
||||
);
|
||||
assert.equal(
|
||||
data[0].name,
|
||||
'Ashley',
|
||||
'The returned first item name is not what expected'
|
||||
);
|
||||
assert.notProperty(
|
||||
data[1],
|
||||
'age',
|
||||
'The returned second item has too many properties'
|
||||
);
|
||||
assert.equal(
|
||||
data[1].name,
|
||||
'Mario',
|
||||
'The returned second item name is not what expected'
|
||||
);
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,88 @@
|
||||
---
|
||||
id: 587d7fb6367417b2b2512c07
|
||||
title: 创建一个模型(Model)
|
||||
challengeType: 2
|
||||
forumTopicId: 301535
|
||||
dashedName: create-a-model
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
**C**RUD 第一小节——CREATE
|
||||
|
||||
首先,我们需要一个 Schema, 每一个 Schema 都对应一个 MongoDB 的 collection, 并且在相应的 collection 里定义 documents 的“样子”。 Schema 用于组成模型(Model), 我们甚至可以通过嵌套 Schema 来创建复杂的模型。目前我们先从简。 我们可以根据模型创建实例,模型实例化后的对象称为 documents。
|
||||
|
||||
Replit 是一个真实的服务器,在其中,通过 handler 函数和数据库交互。 这些函数会在特定事件(比如有人调用了我们的服务器 API)发生时执行。 接下来的挑战题目即是以此为基础。 `done()` 是一个回调函数,它的作用是在一个异步操作(比如对数据库进行插入、查询、更新或删除)执行完成时,通知我们可以继续执行后续的其它代码。 这与 Node.js 中的处理方式十分类似,在 Node.js 中,我们会在(异步操作)成功时调用 `done(null, data)`,在失败时调用 `done(err)`。
|
||||
|
||||
注意:与远程服务器进行交互时,我们需要考虑到发生错误的可能!
|
||||
|
||||
```js
|
||||
/* Example */
|
||||
|
||||
const someFunc = function(done) {
|
||||
//... do something (risky) ...
|
||||
if (error) return done(error);
|
||||
done(null, result);
|
||||
};
|
||||
```
|
||||
|
||||
# --instructions--
|
||||
|
||||
按下面的原型信息创建一个名为 `personSchema` 的 schema:
|
||||
|
||||
```markup
|
||||
- Person Prototype -
|
||||
--------------------
|
||||
name : string [required]
|
||||
age : number
|
||||
favoriteFoods : array of strings (*)
|
||||
```
|
||||
|
||||
采用 Mongoose 基础 schema 类型。 你如果还想添加更多的键,就请使用 required 或 unique 等简单的验证器(validators),并设置默认值。 详情请参考 [Mongoose 文档](http://mongoosejs.com/docs/guide.html)。
|
||||
|
||||
请从 `personSchema` 创建一个名为 `Person` 的 model。
|
||||
|
||||
# --hints--
|
||||
|
||||
应当成功地通过 Mongoose schema 创建实例
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.post(getUserInput('url') + '/_api/mongoose-model', {
|
||||
name: 'Mike',
|
||||
age: 28,
|
||||
favoriteFoods: ['pizza', 'cheese']
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.equal(data.name, 'Mike', '"model.name" is not what expected');
|
||||
assert.equal(data.age, '28', '"model.age" is not what expected');
|
||||
assert.isArray(
|
||||
data.favoriteFoods,
|
||||
'"model.favoriteFoods" is not an Array'
|
||||
);
|
||||
assert.include(
|
||||
data.favoriteFoods,
|
||||
'pizza',
|
||||
'"model.favoriteFoods" does not include the expected items'
|
||||
);
|
||||
assert.include(
|
||||
data.favoriteFoods,
|
||||
'cheese',
|
||||
'"model.favoriteFoods" does not include the expected items'
|
||||
);
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,56 @@
|
||||
---
|
||||
id: 587d7fb6367417b2b2512c09
|
||||
title: 创建并保存一条 Model 记录
|
||||
challengeType: 2
|
||||
forumTopicId: 301536
|
||||
dashedName: create-and-save-a-record-of-a-model
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
在这个挑战中,你需要创建并保存一条模型数据。
|
||||
|
||||
# --instructions--
|
||||
|
||||
在 `createAndSavePerson` 函数中,用我们在上一个挑战中写好的 `Person` 构造函数创建 document 实例, 将包含 `name`、`age` 和 `favoriteFoods` 的对象传给构造函数, 这些属性的数据类型必须符合我们在 `personSchema` 中定义的类型。 然后在返回的 document 实例上调用方法 `document.save()`。 同时,按 Node.js 的方式为它传一个回调函数。 这是一种常见模式,以下所有CRUD方法都将这样的回调函数作为最后一个参数。
|
||||
|
||||
```js
|
||||
/* Example */
|
||||
|
||||
// ...
|
||||
person.save(function(err, data) {
|
||||
// ...do your stuff here...
|
||||
});
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
应成功地创建数据并保存一条数据到数据库
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.get(getUserInput('url') + '/_api/create-and-save-person').then(
|
||||
(data) => {
|
||||
assert.isString(data.name, '"item.name" should be a String');
|
||||
assert.isNumber(data.age, '28', '"item.age" should be a Number');
|
||||
assert.isArray(
|
||||
data.favoriteFoods,
|
||||
'"item.favoriteFoods" should be an Array'
|
||||
);
|
||||
assert.equal(data.__v, 0, 'The db item should be not previously edited');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,68 @@
|
||||
---
|
||||
id: 587d7fb7367417b2b2512c0a
|
||||
title: 使用 model.create() 创建多条记录
|
||||
challengeType: 2
|
||||
forumTopicId: 301537
|
||||
dashedName: create-many-records-with-model-create
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
在一些情况下,比如进行数据库初始化,你会需要创建很多 model 实例来用作初始数据。 `Model.create()` 接受一组像 `[{name: 'John', ...}, {...}, ...]` 的数组作为第一个参数,并将其保存到数据库。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `createManyPeople` 方法,使用 `arrayOfPeople` 作为 `Model.create()` 的参数来创建多个 people 实例。
|
||||
|
||||
**注意:** 你可以使用在上一个挑战中创建的 model 来完成当前挑战。
|
||||
|
||||
# --hints--
|
||||
|
||||
应当成功地一次性创建多条数据
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.ajax({
|
||||
url: getUserInput('url') + '/_api/create-many-people',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify([
|
||||
{ name: 'John', age: 24, favoriteFoods: ['pizza', 'salad'] },
|
||||
{ name: 'Mary', age: 21, favoriteFoods: ['onions', 'chicken'] }
|
||||
])
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.isArray(data, 'the response should be an array');
|
||||
assert.equal(
|
||||
data.length,
|
||||
2,
|
||||
'the response does not contain the expected number of items'
|
||||
);
|
||||
assert.equal(data[0].name, 'John', 'The first item is not correct');
|
||||
assert.equal(
|
||||
data[0].__v,
|
||||
0,
|
||||
'The first item should be not previously edited'
|
||||
);
|
||||
assert.equal(data[1].name, 'Mary', 'The second item is not correct');
|
||||
assert.equal(
|
||||
data[1].__v,
|
||||
0,
|
||||
'The second item should be not previously edited'
|
||||
);
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,57 @@
|
||||
---
|
||||
id: 587d7fb8367417b2b2512c11
|
||||
title: 使用 model.remove() 删除多个 document
|
||||
challengeType: 2
|
||||
forumTopicId: 301538
|
||||
dashedName: delete-many-documents-with-model-remove
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
`Model.remove()` 可以用于删除符合给定匹配条件的所有 document。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `removeManyPeople` 函数,使用 `nameToRemove` 删除所有姓名是变量 `Model.remove()` 的人。 给它传入一个带有 `name` 字段的查询 document 和一个回调函数。
|
||||
|
||||
**注意:** `Model.remove()` 不会返回被删除的 document,而是会返回一个包含操作结果以及受影响的数据数量的 JSON 对象。 不要忘记将它传入 `done()` 回调函数,因为我们需要在挑战的测试中调用它。
|
||||
|
||||
# --hints--
|
||||
|
||||
应一次性成功删除多条数据
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.ajax({
|
||||
url: getUserInput('url') + '/_api/remove-many-people',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify([
|
||||
{ name: 'Mary', age: 16, favoriteFoods: ['lollipop'] },
|
||||
{ name: 'Mary', age: 21, favoriteFoods: ['steak'] }
|
||||
])
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.isTrue(!!data.ok, 'The mongo stats are not what expected');
|
||||
assert.equal(
|
||||
data.n,
|
||||
2,
|
||||
'The number of items affected is not what expected'
|
||||
);
|
||||
assert.equal(data.count, 0, 'the db items count is not what expected');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,53 @@
|
||||
---
|
||||
id: 587d7fb8367417b2b2512c10
|
||||
title: 使用 model.findByIdAndRemove 删除一个 document
|
||||
challengeType: 2
|
||||
forumTopicId: 301539
|
||||
dashedName: delete-one-document-using-model-findbyidandremove
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
`findByIdAndRemove` 和 `findOneAndRemove` 类似于我们之前的更新方法, 它们将被删除的 document 传给数据库。 和之前一样,使用函数参数 `personId` 作为查询关键字。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `removeById` 函数,通过 `_id` 删除一个人的数据, 可以使用 `findByIdAndRemove()` 或 `findOneAndRemove()` 方法。
|
||||
|
||||
# --hints--
|
||||
|
||||
应当成功地删除一条数据
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.post(getUserInput('url') + '/_api/remove-one-person', {
|
||||
name: 'Jason Bourne',
|
||||
age: 36,
|
||||
favoriteFoods: ['apples']
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.equal(data.name, 'Jason Bourne', 'item.name is not what expected');
|
||||
assert.equal(data.age, 36, 'item.age is not what expected');
|
||||
assert.deepEqual(
|
||||
data.favoriteFoods,
|
||||
['apples'],
|
||||
'item.favoriteFoods is not what expected'
|
||||
);
|
||||
assert.equal(data.__v, 0);
|
||||
assert.equal(data.count, 0, 'the db items count is not what expected');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,85 @@
|
||||
---
|
||||
id: 587d7fb6367417b2b2512c06
|
||||
title: 安装和设置 Mongoose
|
||||
challengeType: 2
|
||||
forumTopicId: 301540
|
||||
dashedName: install-and-set-up-mongoose
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
可以采用下面的任意一种方式完成这些挑战:
|
||||
|
||||
- 克隆 [GitHub repo](https://github.com/freeCodeCamp/boilerplate-mongomongoose/) 并在本地完成项目。
|
||||
- 使用[我们的 Replit 上的初始化项目](https://replit.com/github/freeCodeCamp/boilerplate-mongomongoose)来完成项目。
|
||||
- 使用你选择的网站生成器来完成项目, 并确保包含了我们 GitHub 仓库的所有文件。
|
||||
|
||||
当完成本项目,请确认有一个正常运行的 demo 可以公开访问。 然后将 URL 提交到 `Solution Link` 中。
|
||||
|
||||
在这个挑战中,你将建立一个 MongoDB Atlas 数据库并导入连接到它所需的软件包。
|
||||
|
||||
按照<a href='https://www.freecodecamp.org/news/get-started-with-mongodb-atlas/' rel='noopener noreferrer' target='_blank'>这篇教程</a>在 MongoDB Atlas 创建一个托管数据库。
|
||||
|
||||
# --instructions--
|
||||
|
||||
将 `mongodb` 和 `mongoose` 添加到项目的 `package.json` 文件中。 然后,在 `myApp.js` 文件中请求 `mongoose`。 创建一个 `.env` 文件,给它添加一个 `MONGO_URI` 变量。 变量的值为你的 MongoDB Atlas 数据库 URI。 应用单引号或双引号包裹 URI。请记住,环境变量 `=` 两边不能有空格。 例如,`MONGO_URI='VALUE'`。 完成后,使用下面的代码来连接数据库。
|
||||
|
||||
```js
|
||||
mongoose.connect(<Your URI>, { useNewUrlParser: true, useUnifiedTopology: true });
|
||||
```
|
||||
|
||||
# --hints--
|
||||
|
||||
“mongodb” 应在 package.json 中作为依赖项定义。
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.get(getUserInput('url') + '/_api/file/package.json').then(
|
||||
(data) => {
|
||||
var packJson = JSON.parse(data);
|
||||
assert.property(packJson.dependencies, 'mongodb');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
“mongoose” 应在 package.json 中作为依赖项定义。
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.get(getUserInput('url') + '/_api/file/package.json').then(
|
||||
(data) => {
|
||||
var packJson = JSON.parse(data);
|
||||
assert.property(packJson.dependencies, 'mongoose');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
应使用 “mongoose” 连接数据库。
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.get(getUserInput('url') + '/_api/is-mongoose-ok').then(
|
||||
(data) => {
|
||||
assert.isTrue(data.isMongooseOk, 'mongoose is not connected');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,54 @@
|
||||
---
|
||||
id: 587d7fb8367417b2b2512c0e
|
||||
title: '通过执行查询、编辑、保存来执行经典更新流程'
|
||||
challengeType: 2
|
||||
forumTopicId: 301541
|
||||
dashedName: perform-classic-updates-by-running-find-edit-then-save
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
在过去,如果想要编辑 document 并以某种方式使用它(比如放到服务器的返回数据中),就必须执行查找、编辑和保存。 Mongoose 有一个专用的更新方法 `Model.update()`, 它与底层的 mongo 驱动绑定。 通过这个方法,我们可以批量编辑符合特定条件的多个 document。但问题在于,这个方法不会返回更新后的 document,而是返回状态信息。 此外,它直接调用 mongo 的底层驱动,让处理 model 的验证变得更加棘手。
|
||||
|
||||
# --instructions--
|
||||
|
||||
在这个挑战中,请使用参数 `personId` 作为字段,修改 `findEditThenSave` 方法,以在数据库中通过 `_id` 找到相应的 person(你可以使用之前挑战中的任何一种方法)。 将 `"hamburger"` 添加到它的 `favoriteFoods` 清单中(你可以使用 `Array.push()`)。 然后,在查询数据库的方法的回调里通过 `save()` 方法更新 `Person` 的数据。
|
||||
|
||||
**提示:** 如果你在 Schema 中将 `favoriteFoods` 声明为一个 Array(数组)并且没有指定数组的类型(如 `[String]`), 那么此时,`favoriteFoods` 就会是默认的 Mixed 类型。如果想编辑它,就必须执行 `document.markModified('edited-field')`。 详情请参阅 [Mongoose 文档](https://mongoosejs.com/docs/schematypes.html#Mixed)
|
||||
|
||||
# --hints--
|
||||
|
||||
应成功地对一条数据进行查找、编辑和更新
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.post(getUserInput('url') + '/_api/find-edit-save', {
|
||||
name: 'Poldo',
|
||||
age: 40,
|
||||
favoriteFoods: ['spaghetti']
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.equal(data.name, 'Poldo', 'item.name is not what is expected');
|
||||
assert.equal(data.age, 40, 'item.age is not what expected');
|
||||
assert.deepEqual(
|
||||
data.favoriteFoods,
|
||||
['spaghetti', 'hamburger'],
|
||||
'item.favoriteFoods is not what expected'
|
||||
);
|
||||
assert.equal(data.__v, 1, 'The item should be previously edited');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,58 @@
|
||||
---
|
||||
id: 587d7fb8367417b2b2512c0f
|
||||
title: 在 document 中执行新的更新方式——使用 model.findOneAndUpdate()
|
||||
challengeType: 2
|
||||
forumTopicId: 301542
|
||||
dashedName: perform-new-updates-on-a-document-using-model-findoneandupdate
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
最近发布的 mongoose 版本简化了 document 的更新方式, 但同时,一些高级功能(如 pre/post hook, 验证)的使用方式也变得和以前不同。因此,在很多情景下,上一个挑战中提到的老方法其实更常用。 新方法的加入,可以让我们使用 `findByIdAndUpdate()` 来进行基于 id 的搜索。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `findAndUpdate` 函数,通过 `Name` 查询人,并将查到的人的年龄设为 `20` 岁, 将函数参数 `personName` 作为查询关键字。
|
||||
|
||||
**提示:** 你需要返回更新后的 document。 你可以把 `findOneAndUpdate()` 的第三个参数设置为 `{ new: true }` 。 默认情况下,这个方法会返回修改前的数据。
|
||||
|
||||
# --hints--
|
||||
|
||||
应成功地使用 findOneAndUpdate 更新数据
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.post(getUserInput('url') + '/_api/find-one-update', {
|
||||
name: 'Dorian Gray',
|
||||
age: 35,
|
||||
favoriteFoods: ['unknown']
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.equal(data.name, 'Dorian Gray', 'item.name is not what expected');
|
||||
assert.equal(data.age, 20, 'item.age is not what expected');
|
||||
assert.deepEqual(
|
||||
data.favoriteFoods,
|
||||
['unknown'],
|
||||
'item.favoriteFoods is not what expected'
|
||||
);
|
||||
assert.equal(
|
||||
data.__v,
|
||||
0,
|
||||
'findOneAndUpdate does not increment version by design!'
|
||||
);
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,53 @@
|
||||
---
|
||||
id: 587d7fb7367417b2b2512c0b
|
||||
title: 使用 model.find() 查询数据库
|
||||
challengeType: 2
|
||||
forumTopicId: 301543
|
||||
dashedName: use-model-find-to-search-your-database
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
我们尝试一种最简单的用法,`Model.find()` 接收一个查询 document(一个 JSON 对象)作为第一个参数,一个回调函数作为第二个参数, 它会返回由匹配到的数据组成的数组。 这个方法支持很多搜索选项, 详情请参阅文档。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `findPeopleByName` 函数使用 <code>Model.find() -\> [Person]</code> 查询所有给定名字的人。
|
||||
|
||||
请使用函数参数中的 `personName` 作为搜索条件。
|
||||
|
||||
# --hints--
|
||||
|
||||
应成功地找到所有符合条件的数据
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.post(getUserInput('url') + '/_api/find-all-by-name', {
|
||||
name: 'r@nd0mN4m3',
|
||||
age: 24,
|
||||
favoriteFoods: ['pizza']
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.isArray(data, 'the response should be an Array');
|
||||
assert.equal(
|
||||
data[0].name,
|
||||
'r@nd0mN4m3',
|
||||
'item.name is not what expected'
|
||||
);
|
||||
assert.equal(data[0].__v, 0, 'The item should be not previously edited');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,48 @@
|
||||
---
|
||||
id: 587d7fb7367417b2b2512c0d
|
||||
title: 使用 model.findById() 方法,根据 _id 来搜索数据
|
||||
challengeType: 2
|
||||
forumTopicId: 301544
|
||||
dashedName: use-model-findbyid-to-search-your-database-by-id
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
在保存 document 的时候,MongoDB 会自动为它添加 `_id` 字段,并给该字段设置一个唯一的仅包含数字和字母的值。 通过 `_id` 搜索是一个十分常见的操作,为此,Mongoose 提供了一个专门的方法。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `findPersonById`,用 `Model.findById() -> Person` 来查询唯一一个给定 `_id` 的人, 把函数参数 `personId` 作为查询键。
|
||||
|
||||
# --hints--
|
||||
|
||||
应成功地根据 Id 找到对应的数据
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.get(getUserInput('url') + '/_api/find-by-id').then(
|
||||
(data) => {
|
||||
assert.equal(data.name, 'test', 'item.name is not what expected');
|
||||
assert.equal(data.age, 0, 'item.age is not what expected');
|
||||
assert.deepEqual(
|
||||
data.favoriteFoods,
|
||||
['none'],
|
||||
'item.favoriteFoods is not what expected'
|
||||
);
|
||||
assert.equal(data.__v, 0, 'The item should be not previously edited');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
@ -0,0 +1,51 @@
|
||||
---
|
||||
id: 587d7fb7367417b2b2512c0c
|
||||
title: 使用 model.findOne() 从数据库中返回一个单一匹配的 Document
|
||||
challengeType: 2
|
||||
forumTopicId: 301545
|
||||
dashedName: use-model-findone-to-return-a-single-matching-document-from-your-database
|
||||
---
|
||||
|
||||
# --description--
|
||||
|
||||
`Model.findOne()` 与 `Model.find()` 十分类似,但就算数据库中有很多条数据可以匹配查询条件,它也只返回一个 document,而不会返回一个数组, 如果查询条件是声明为唯一值的属性,它会更加适用。
|
||||
|
||||
# --instructions--
|
||||
|
||||
修改 `findOneByFood` 函数,用 `Model.findOne() -> Person` 来查询在收藏夹中有某种食物的一个人。 将函数参数中的 `food` 作为检索条件。
|
||||
|
||||
# --hints--
|
||||
|
||||
应成功地找到一个数据
|
||||
|
||||
```js
|
||||
(getUserInput) =>
|
||||
$.post(getUserInput('url') + '/_api/find-one-by-food', {
|
||||
name: 'Gary',
|
||||
age: 46,
|
||||
favoriteFoods: ['chicken salad']
|
||||
}).then(
|
||||
(data) => {
|
||||
assert.equal(data.name, 'Gary', 'item.name is not what expected');
|
||||
assert.deepEqual(
|
||||
data.favoriteFoods,
|
||||
['chicken salad'],
|
||||
'item.favoriteFoods is not what expected'
|
||||
);
|
||||
assert.equal(data.__v, 0, 'The item should be not previously edited');
|
||||
},
|
||||
(xhr) => {
|
||||
throw new Error(xhr.responseText);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
# --solutions--
|
||||
|
||||
```js
|
||||
/**
|
||||
Backend challenges don't need solutions,
|
||||
because they would need to be tested against a full working project.
|
||||
Please check our contributing guidelines to learn more.
|
||||
*/
|
||||
```
|
Reference in New Issue
Block a user