Danh sách câu hỏi của đề

Câu hỏi: SDN302 Server-Side development with NodeJS, Express, and MongoDB – Bộ ôn tập cuối kỳ số 3

50 câu trắc nghiệm kèm lời giải của môn Server-Side development with NodeJS, Express, and MongoDB, xếp đúng thứ tự trong đề.

Danh sách câu hỏi

20/50 câuCòn 30
1What is a significant difference between a load balancer and an API Gateway?4 lựa chọnDễ100% trả lời đúng
AA load balancer distributes network traffic across multiple servers.
BAn API Gateway primarily routes requests to backend services.
CA load balancer handles request aggregation.
DAn API Gateway manages server health checks.
Lời giải
Đáp án đúng gồm hai ý: "A load balancer distributes network traffic across multiple servers." và "An API Gateway primarily routes requests to backend services.". Load balancer (bộ cân bằng tải) làm việc ở tầng mạng hoặc HTTP, chia lưu lượng cho nhiều bản sao của cùng một dịch vụ để tăng khả năng chịu tải; API Gateway là cửa vào duy nhất của hệ microservices, đọc đường dẫn và phương thức để chuyển request tới đúng dịch vụ phía sau, kèm xác thực, giới hạn tốc độ (rate limiting). "A load balancer handles request aggregation." sai vì gộp kết quả từ nhiều dịch vụ thành một phản hồi (aggregation) là tính năng điển hình của API Gateway, còn load balancer chỉ chuyển nguyên request tới một máy. "An API Gateway manages server health checks." gán nhầm vai trò: kiểm tra sức khoẻ (health check) để loại máy hỏng khỏi nhóm là việc cốt lõi của load balancer; gateway có thể dựa vào kết quả đó nhưng đó không phải điểm khác biệt chính giữa hai thành phần.
Mở trang câu hỏi này →
2What keyword is used in a schema to define a reference for population?4 lựa chọnTrung bình67% trả lời đúng
Aref
Blink
Cpopulate
Djoin
Lời giải
Đáp án đúng: "ref". Trong schema Mongoose, trường tham chiếu khai báo dạng author: { type: Schema.Types.ObjectId, ref: 'User' }; ref là tên model mà ObjectId trỏ tới, và populate() đọc ref để biết phải truy vấn collection nào khi thay id bằng tài liệu đầy đủ. "link" không phải tuỳ chọn schema của Mongoose, khai báo nó không tạo liên kết nào. "populate" là tên method gọi trên query lúc truy vấn, ví dụ Post.find().populate('author'), chứ không phải từ khoá đặt trong định nghĩa schema. "join" là khái niệm phép nối của SQL; Mongoose không có từ khoá join, việc nối dữ liệu được làm bằng populate hoặc giai đoạn $lookup của aggregation.
Mở trang câu hỏi này →
A@Injectable
B@Inject
C@Service
D@Provider
Lời giải
Đáp án đúng: "@Inject". Trong NestJS, @Inject(token) là decorator thực hiện việc tiêm phụ thuộc (dependency injection) một cách tường minh: đặt trước tham số của hàm dựng, nó báo cho IoC container biết cần lấy provider nào theo token, ví dụ constructor(@Inject('CONFIG') config), đặc biệt khi token là chuỗi hay symbol chứ không phải class. Cần phân biệt rõ với "@Injectable": decorator này đánh dấu một class là provider để Nest quản lý và có thể được tiêm vào nơi khác, nó cũng thường đặt trên chính service nhận phụ thuộc, nhưng bản thân nó không chỉ định thứ gì được tiêm vào; khi tiêm theo kiểu class thì Nest tự suy ra từ kiểu tham số, còn decorator làm việc tiêm là @Inject. "@Service" không phải decorator của NestJS, đó là cách gọi trong framework khác như Spring. "@Provider" cũng không tồn tại trong NestJS; provider được khai báo qua mảng providers của @Module.
Mở trang câu hỏi này →
ATo render HTML pages
BTo define document structure, validation, and rules
CTo replace MongoDB server
DTo encrypt collections automatically
Lời giải
Đáp án đúng: "To define document structure, validation, and rules". Mongoose là một ODM (Object Data Modeling, ánh xạ đối tượng sang dữ liệu) cho MongoDB, và Schema là nơi mô tả hình dạng của document trong một collection: có những trường nào, kiểu dữ liệu ra sao, ràng buộc như required, min, max, enum, giá trị mặc định, cùng các hook và phương thức. MongoDB vốn không ép cấu trúc, nên schema giúp ứng dụng giữ dữ liệu nhất quán trước khi lưu. "To render HTML pages" là việc của view engine như EJS, Pug hay Handlebars qua res.render, không liên quan tới schema. "To replace MongoDB server" sai vì Mongoose chạy trong ứng dụng Node.js và vẫn cần một máy chủ MongoDB thật để kết nối qua driver. "To encrypt collections automatically" sai vì schema không mã hoá dữ liệu; mã hoá cấp trường là tính năng riêng của MongoDB như Client-Side Field Level Encryption, không phải mục đích của schema.
Mở trang câu hỏi này →
AStore as plain text
BHash and salt before storing
CUse Base64 encoding
DEncrypt using SSL
Lời giải
Đáp án đúng: "Hash and salt before storing". Mật khẩu nên đi qua hàm băm (hash) một chiều, chậm có chủ đích như bcrypt, kèm salt là chuỗi ngẫu nhiên riêng cho từng người, nên hai người cùng mật khẩu vẫn ra hai giá trị băm khác nhau và bảng tra sẵn (rainbow table) mất tác dụng; khi đăng nhập, bcrypt.compare băm lại mật khẩu vừa nhập để so khớp. "Store as plain text" sai vì chỉ cần lộ cơ sở dữ liệu là lộ toàn bộ mật khẩu. "Use Base64 encoding" sai vì Base64 chỉ là cách biểu diễn ký tự, ai cũng giải ngược được ngay, không có bí mật nào. "Encrypt using SSL" sai vì SSL/TLS chỉ bảo vệ dữ liệu trên đường truyền giữa client và máy chủ, không bảo vệ dữ liệu đã nằm trong cơ sở dữ liệu.
Mở trang câu hỏi này →
Đề bài
const fs = require('fs');
function readTwoFiles(file1, file2, callback) {
  fs.readFile(file1, 'utf8', (err, data1) => {
    if (err) return callback(err);
    fs.readFile(file2, 'utf8', (err, data2) => {
      if (err) return callback(err);
      callback(null, data1 + data2);
    });
  });
}
readTwoFiles('file1.txt', 'file2.txt', (err, result) => {
  if (err) {
    console.log('Error:', err.message);
  } else {
    console.log('Result:', result);
  }
});

Assume 'file1.txt' contains "Hello" and 'file2.txt' does NOT exist.

AResult: Hello
BError: ENOENT: no such file or directory, open 'file2.txt'
CError: ENOENT: no such file or directory, open 'file1.txt'
DResult: undefined
Lời giải
Đáp án đúng: "Error: ENOENT: no such file or directory, open 'file2.txt'". Lần theo mã: readTwoFiles gọi fs.readFile cho file1.txt, tệp tồn tại nên err là null và data1 bằng Hello; trong callback đó nó gọi tiếp fs.readFile cho file2.txt, tệp không tồn tại nên Node trả lỗi có code ENOENT với thông điệp no such file or directory, open 'file2.txt'; nhánh if (err) return callback(err) chuyển lỗi ra ngoài và callback cuối chạy console.log('Error:', err.message), in chữ Error: rồi một dấu cách và thông điệp lỗi. "Result: Hello" sai vì callback(null, data1 + data2) chỉ chạy khi cả hai lần đọc đều thành công. "Error: ENOENT: no such file or directory, open 'file1.txt'" sai vì file1.txt đọc được, lỗi phát sinh ở tệp thứ hai. "Result: undefined" sai vì khi có lỗi mã thoát sớm bằng return, nhánh in Result không bao giờ chạy.
Mở trang câu hỏi này →
AIt does not support any query language
BIt stores data mainly as flexible documents instead of relational tables
CIt only works without internet connection
DIt cannot store structured data
Lời giải
Đáp án đúng: "It stores data mainly as flexible documents instead of relational tables". NoSQL (không chỉ SQL) chỉ nhóm cơ sở dữ liệu không dùng mô hình bảng quan hệ; MongoDB là cơ sở dữ liệu hướng tài liệu, lưu dữ liệu thành các document BSON trong collection, mỗi document có thể có cấu trúc khác nhau và lồng mảng, object con, thay vì hàng và cột cố định nối nhau bằng khoá ngoại. "It does not support any query language" sai vì MongoDB có ngôn ngữ truy vấn riêng (MQL) với find, các toán tử như $gt, $in và aggregation pipeline. "It only works without internet connection" sai vì MongoDB là máy chủ phục vụ qua mạng, kể cả dịch vụ đám mây Atlas. "It cannot store structured data" sai vì document vẫn có cấu trúc rõ ràng và Mongoose còn cho định nghĩa schema chặt chẽ; khác biệt là cấu trúc linh hoạt chứ không phải không có cấu trúc.
Mở trang câu hỏi này →
A/getOrdersByCustomer/88
B/orders/customer/88/get
C/customers/88/orders
D/orders?id=88&customer=true
Lời giải
Đáp án đúng: "/customers/88/orders". Thiết kế REST đặt tên endpoint theo danh từ chỉ tài nguyên, để phương thức HTTP nói lên hành động, và biểu diễn quan hệ cha con bằng đường dẫn lồng: /customers/88 là khách hàng id 88, thêm /orders là tập đơn hàng thuộc khách đó, gọi bằng GET là đọc. "/getOrdersByCustomer/88" nhét động từ get vào URL theo kiểu gọi hàm (RPC), trùng lặp với ý nghĩa của phương thức GET và khó mở rộng thành bộ endpoint thống nhất. "/orders/customer/88/get" vừa có động từ get ở cuối, vừa dùng customer số ít làm đoạn trung gian không phải một tài nguyên rõ ràng. "/orders?id=88&customer=true" gây hiểu nhầm: tham số id thường hiểu là id của chính đơn hàng, còn customer=true là cờ mơ hồ; nếu muốn lọc bằng query thì phải viết rõ kiểu customerId bằng 88.
Mở trang câu hỏi này →
ACreating separate documents for related data
BNormalize your data
CUse data types efficiently
DStore large binary data in documents
Lời giải
Đáp án đúng gồm ba ý: "Creating separate documents for related data", "Normalize your data" và "Use data types efficiently". Giới hạn 16 MB áp cho từng tài liệu BSON, nên cách tránh là giữ mỗi tài liệu gọn: tách dữ liệu liên quan có thể phình to (như danh sách bình luận tăng mãi) ra tài liệu riêng và liên kết bằng ObjectId, tức chuẩn hoá (normalize) thay vì nhúng (embed) mọi thứ vào một tài liệu, đồng thời chọn kiểu dữ liệu tiết kiệm như lưu số bằng Number thay vì chuỗi, lưu ngày bằng Date. "Store large binary data in documents" làm ngược lại vì ảnh, video hay tệp lớn nhét thẳng vào tài liệu sẽ nhanh chóng chạm 16 MB; MongoDB khuyên dùng GridFS, chia tệp thành nhiều khối (chunk) lưu ở collection riêng, hoặc lưu tệp ở kho đối tượng và chỉ giữ đường dẫn trong tài liệu.
Mở trang câu hỏi này →
A.populate() only works with arrays
BWrong path name used in populate
Cfind() must come after populate
DObjectId cannot reference User model
Lời giải
Đáp án đúng: "Wrong path name used in populate". Đối số của populate() là tên đường dẫn (path) có trong schema chứ không phải tên tuỳ ý; schema chỉ có trường author với ref tới User, còn mã lại gọi populate với writer. Từ Mongoose 6, tuỳ chọn strictPopulate mặc định bật nên lệnh này ném lỗi báo không thể populate path writer vì nó không có trong schema; ở bản cũ hơn nó lặng lẽ không làm gì và author vẫn là ObjectId. Cách sửa là populate với author. ".populate() only works with arrays" sai vì populate dùng được cho cả trường ObjectId đơn lẫn mảng ObjectId. "find() must come after populate" sai vì populate là method nối vào query do find() trả về, nên thứ tự Post.find().populate(...) là đúng. "ObjectId cannot reference User model" sai vì khai báo type ObjectId kèm ref tới User chính là cách tham chiếu chuẩn.
Mở trang câu hỏi này →
AUser.saveAll()
BUser.insertOne()
CUser.create({...})
DUser.make({...})
Lời giải

Đáp án đúng: "

Lời giải
User.create({
  ...
}

)". Trong Mongoose, Model.create(doc) dựng một document từ object truyền vào, chạy validation và các pre hook save, lưu xuống MongoDB rồi trả về Promise chứa chính document vừa tạo, đã có _id và các giá trị mặc định, nên đáp ứng đủ hai yêu cầu chèn mới và trả về đối tượng. "User.insertOne()" gợi nhớ phương thức insertOne của collection trong driver mongodb gốc, vốn chỉ trả về object xác nhận chứa insertedId chứ không trả về tài liệu đã tạo, và lời gọi rỗng như vậy cũng không có dữ liệu để chèn. "User.saveAll()" không tồn tại trong Mongoose; save() là phương thức của từng document, còn chèn nhiều tài liệu thì dùng insertMany(). "

Lời giải
User.make({
  ...
}

)" cũng không phải API nào của Mongoose.

Mở trang câu hỏi này →
AAWS
BHeroku
CFirebase
DDigitalOcean
Lời giải
Đáp án đúng: "Firebase". BaaS (Backend as a Service, phần phụ trợ dưới dạng dịch vụ) cung cấp sẵn những khối mà ứng dụng thường phải tự viết ở máy chủ: cơ sở dữ liệu, xác thực, lưu trữ tệp, hàm chạy phía máy chủ. Firebase thuộc Google, nổi bật với Cloud Firestore (cơ sở dữ liệu NoSQL dạng document đồng bộ thời gian thực), Cloud Functions (hàm serverless chạy khi có sự kiện), Authentication và Hosting. "AWS" là nền tảng đám mây của Amazon; AWS cũng có dịch vụ kiểu BaaS là Amplify, nhưng không phải của Google và không có Firestore. "Heroku" là PaaS (nền tảng triển khai ứng dụng) thuộc Salesforce, nơi bạn đưa mã máy chủ của mình lên chạy chứ không có sẵn Firestore hay Cloud Functions. "DigitalOcean" là nhà cung cấp hạ tầng đám mây như máy ảo Droplet, thuộc nhóm IaaS, cũng không do Google phát triển.
Mở trang câu hỏi này →
ACreates new author documents
BReplaces referenced ObjectId with actual related author document
CSorts authors alphabetically
DEncrypts author field
Lời giải
Đáp án đúng: "Replaces referenced ObjectId with actual related author document". Khi trường author của schema lưu ObjectId kèm ref tới model tác giả, lời gọi populate với tên trường author làm Mongoose chạy thêm một truy vấn vào collection được tham chiếu và thay giá trị ObjectId trong kết quả bằng nguyên tài liệu tác giả, nên có thể đọc ngay post.author.name; dữ liệu lưu trong cơ sở dữ liệu vẫn chỉ là ObjectId. "Creates new author documents" sai vì populate chỉ đọc, không ghi tài liệu nào. "Sorts authors alphabetically" sai vì sắp xếp là việc của sort(); populate có thể nhận tuỳ chọn sắp xếp cho tài liệu con nhưng tự nó không sắp xếp. "Encrypts author field" sai vì populate không mã hoá dữ liệu; mã hoá trường cần plugin hoặc tính năng mã hoá riêng của MongoDB.
Mở trang câu hỏi này →
AarticleRouter.route('/:id').delete(articleController.delete)
BarticleRouter.route('/').delete(articleController.delete)
CarticleRouter.route('/:id').get(articleController.delete)
DarticleRouter.route('/:id').post(articleController.delete)
Lời giải
Đáp án đúng: "articleRouter.route('/:id').delete(articleController.delete)". Xoá một bài viết cụ thể cần hai điều: method HTTP DELETE theo quy ước REST, và tham số đường dẫn :id để biết bài nào; router.route('/:id') gom các handler của cùng một đường dẫn, .delete(...) gắn handler cho method DELETE, còn trong controller lấy id qua req.params.id. "articleRouter.route('/').delete(articleController.delete)" thiếu :id nên đường dẫn trỏ tới cả tập bài viết, không xác định được bài cần xoá. "articleRouter.route('/:id').get(articleController.delete)" gắn handler xoá vào GET, trái ngữ nghĩa REST vì GET phải an toàn, chỉ đọc. "articleRouter.route('/:id').post(articleController.delete)" dùng POST vốn dành cho tạo mới, nên yêu cầu DELETE tới /:id sẽ không khớp route này.
Mở trang câu hỏi này →
15Which of the following statements correctly describe Serialization?4 lựa chọnKhó25% trả lời đúng
ASerialization converts an object into a stream of bytes.
BSerialization is used to convert data into JSON format.
CSerialization saves the state of the object in an easily transmittable form.
DSerialization compresses data to save storage space.
Lời giải
Đáp án đúng gồm hai ý: "Serialization converts an object into a stream of bytes." và "Serialization saves the state of the object in an easily transmittable form.". Tuần tự hoá (serialization) là biến một đối tượng trong bộ nhớ, vốn gồm các tham chiếu chỉ có nghĩa trong tiến trình đang chạy, thành chuỗi byte hay chuỗi ký tự tuyến tính để ghi ra tệp, lưu cơ sở dữ liệu hoặc gửi qua mạng; phía nhận giải tuần tự (deserialization) để dựng lại đối tượng có cùng trạng thái. "Serialization is used to convert data into JSON format." chỉ là một trường hợp riêng: JSON.stringify là dạng serialization phổ biến trong Node.js, nhưng MongoDB dùng BSON, nhiều hệ dùng Protocol Buffers hay MessagePack, nên serialization không gắn riêng với JSON. "Serialization compresses data to save storage space." sai vì nén là bước khác như gzip; bản tuần tự hoá thậm chí có thể dài hơn dữ liệu gốc.
Mở trang câu hỏi này →
AGET
BPUT
CDELETE
DPOST
Lời giải
Đáp án đúng: "PUT". Theo ngữ nghĩa HTTP dùng trong REST, PUT gửi biểu diễn mới của một tài nguyên tới URL của nó, ví dụ PUT /users/5 kèm body chứa dữ liệu cập nhật, để thay thế trạng thái hiện có; PUT có tính idempotent (lặp lại nhiều lần cho cùng kết quả). Ngoài ra còn PATCH dành cho cập nhật một phần, nhưng PATCH không có trong danh sách. "GET" chỉ đọc tài nguyên và không được làm thay đổi dữ liệu trên máy chủ. "DELETE" xoá tài nguyên chứ không cập nhật nó. "POST" theo quy ước dùng để tạo tài nguyên mới trong một tập hợp, như POST /users; về kỹ thuật POST có thể làm nhiều việc, nhưng khi phân vai CRUD chuẩn thì cập nhật tài nguyên đã có thuộc về PUT.
Mở trang câu hỏi này →
Đề bài
const express = require('express');
const app = express();

app.get('/users', (req, res) => {
  res.send('GET request to the /users endpoint');
});

app.post('/users', (req, res) => {
  res.send('POST request to the /users endpoint');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});
AThe /users endpoint handles GET requests.
BThe /users endpoint handles POST requests.
CThe /users endpoint handles PUT requests.
DThe /users endpoint handles DELETE requests.
Lời giải
Đáp án đúng gồm hai ý: "The /users endpoint handles GET requests." và "The /users endpoint handles POST requests.". Lần theo mã: app được tạo từ express(), dòng app.get('/users', …) đăng ký một handler chỉ chạy khi request dùng phương thức GET tới /users và trả chuỗi GET request to the /users endpoint; dòng app.post('/users', …) đăng ký handler thứ hai cho cùng đường dẫn nhưng chỉ khớp phương thức POST; cuối cùng app.listen(3000) mở cổng 3000. Express khớp route theo cả phương thức lẫn đường dẫn, nên một URL có thể có nhiều handler khác nhau. "The /users endpoint handles PUT requests." sai vì không có app.put nào, request PUT tới /users rơi xuống xử lý mặc định và nhận 404 với thông báo Cannot PUT /users. "The /users endpoint handles DELETE requests." sai tương tự vì thiếu app.delete, request DELETE cũng nhận 404.
Mở trang câu hỏi này →
Đề bài
const mongoose = require('mongoose');
const userSchema = new mongoose.____({
  name: String,
  age: Number
});
AModel
BSchema
CDocument
DCollection
Lời giải

Đáp án đúng: "Schema". Hàm khởi tạo mongoose.Schema nhận một đối tượng mô tả các trường và kiểu, ở đây name là String và age là Number, nên chỗ trống phải điền Schema để có new mongoose.Schema(...); schema chỉ là bản thiết kế cấu trúc và quy tắc kiểm tra dữ liệu. "Model" sai vì model được tạo từ schema bằng mongoose.model('User', userSchema), không khởi tạo bằng new với đối tượng định nghĩa trường. "Document" là một bản ghi cụ thể, tức một thể hiện của model, ví dụ tạo bằng new User(...). "Collection" là tập hợp tài liệu trong MongoDB mà model ánh xạ tới, Mongoose tự đặt tên theo model, không dùng để khai báo schema.

Mở trang câu hỏi này →
ADatabase that runs the same everywhere
BMongoDB stores data in flexible, JSON-like documents
CMongoDB is a distributed database at its core, allowing you to intelligently put data where you want it
DMongoDB is a relational SQL
Lời giải
Đáp án đúng: "MongoDB is a relational SQL". Câu hỏi tìm phát biểu sai, và đây là phát biểu sai vì MongoDB là cơ sở dữ liệu NoSQL hướng tài liệu, không tổ chức dữ liệu thành bảng quan hệ và không dùng ngôn ngữ SQL; nó truy vấn bằng MQL với các hàm như find() và aggregate(). "Database that runs the same everywhere" là khẩu hiệu đúng của MongoDB, vì cùng một hệ chạy được trên máy cá nhân, máy chủ riêng hay đám mây Atlas, nên không được chọn. "MongoDB stores data in flexible, JSON-like documents" đúng vì dữ liệu lưu thành document BSON có cấu trúc linh hoạt, nên cũng không được chọn. "MongoDB is a distributed database at its core" cũng đúng vì MongoDB được thiết kế sẵn cho replica set (sao chép dữ liệu) và sharding (chia dữ liệu theo khoá phân mảnh lên nhiều máy), cho phép đặt dữ liệu ở nơi mong muốn, nên không phải phát biểu sai.
Mở trang câu hỏi này →
AThe file was uploaded successfully
BThe request did not contain a file
CThe file is too large
DThe server rejected the file type
Lời giải
Đáp án đúng: "The request did not contain a file". Khi gắn upload.single('avatar') vào route, multer chỉ tạo đối tượng req.file nếu request multipart thật sự có một tệp trong trường avatar; không có tệp nào được gửi thì multer vẫn cho request đi tiếp và req.file là undefined, nên route nên kiểm tra điều này để trả lỗi 400. "The file was uploaded successfully" ngược lại: tải lên thành công thì req.file là một đối tượng có fieldname, originalname, mimetype, size và path hoặc buffer. "The file is too large" sai vì vượt limits.fileSize khiến multer gọi next với MulterError mã LIMIT_FILE_SIZE, request chuyển sang middleware xử lý lỗi chứ không tới route với req.file undefined. "The server rejected the file type" thường được làm trong fileFilter bằng cách trả về lỗi; nếu fileFilter chỉ gọi callback với false thì tệp bị bỏ qua và req.file cũng undefined, nhưng đó là trường hợp do chính lập trình viên cấu hình, còn ý nghĩa trực tiếp của req.file undefined là không có tệp đi kèm request.
Mở trang câu hỏi này →