Giới thiệu dự án

Thị trường công nghệ thông tin (CNTT) tại Việt Nam trong kỷ nguyên số chứng kiến sự bùng nổ mạnh mẽ về nhu cầu nhân lực chất lượng cao. Theo báo cáo thống kê từ Bộ Thông tin và Truyền thông, đến năm 2020, toàn ngành đối mặt với tình trạng thiếu hụt hơn 500.000 nhân sự IT. Mặc dù làn sóng chuyển dịch công nghệ và thành lập các trung tâm phát triển phần mềm diễn ra sôi động, các nền tảng tuyển dụng truyền thống vẫn bộc lộ nhiều điểm nghẽn nghiêm trọng: giao diện đa ngành phân mảnh, tốc độ phản hồi chậm do kiến trúc kết xuất phía máy chủ (Server-Side Rendering - SSR) thế hệ cũ, thiếu cơ chế tìm kiếm chuyên sâu theo ngăn xếp công nghệ (tech stack), và không có hệ thống đánh giá văn hóa doanh nghiệp minh bạch dành riêng cho giới lập trình viên.

Đề tài "Xây dựng Website tìm việc IT trên nền tảng MEAN Stack" được nghiên cứu và phát triển bởi sinh viên Đỗ Quốc Việt và Nguyễn Thế Vinh dưới sự hướng dẫn của ThS. Nguyễn Minh Đạo tại Khoa Công nghệ Thông tin - Trường Đại học Sư phạm Kỹ thuật TP.HCM. Dự án tập trung giải quyết triệt để bài toán kết nối tuyển dụng trong lĩnh vực CNTT thông qua việc ứng dụng trọn vẹn kiến trúc Full-stack JavaScript hiện đại.

+-------------------------------------------------------------------------+
|                           MEAN STACK ARCHITECTURE                       |
|                                                                         |
|  +--------------------+        HTTP/JSON        +--------------------+  |
|  |     Angular 7      |  <===================>  |    Express.js      |  |
|  |  (Single Page App) |    RESTful API Layer    |  (Node.js Runtime) |  |
|  +--------------------+                         +---------+----------+  |
|            |                                              |             |
|            | S3 Direct/SDK Upload                         | Mongoose    |
|            v                                              v             |
|  +--------------------+                         +--------------------+  |
|  |   Amazon Web S3    |                         |      MongoDB       |  |
|  |  (Static Assets)   |                         |  (Document Store)  |  |
|  +--------------------+                         +---------+----------+  |
|                                                           | Dual Sync   |
|                                                           v             |
|                                                 +--------------------+  |
|                                                 |   Elasticsearch    |  |
|                                                 |  (Docker Cluster)  |  |
|                                                 +--------------------+  |
+-------------------------------------------------------------------------+

Mục tiêu dự án

  1. Làm chủ và ứng dụng toàn diện hệ sinh thái MEAN Stack: Khai thác sức mạnh đồng nhất của ngôn ngữ JavaScript từ tầng cơ sở dữ liệu (MongoDB), tầng logic phía máy chủ (ExpressJS, NodeJS) đến tầng giao diện người dùng (Angular 7 với TypeScript).
  2. Xây dựng kiến trúc Single Page Application (SPA) chuẩn mực: Tối ưu hóa trải nghiệm tương tác không tải lại trang (Zero-reload), giảm thiểu tải trọng đường truyền (payload) qua giao thức RESTful API phi trạng thái (Stateless).
  3. Tích hợp Search Engine phân tán Elasticsearch trên nền tảng Docker: Nâng cao độ chính xác và tốc độ truy vấn bài đăng tuyển dụng theo kỹ năng, ngôn ngữ, vị trí địa lý với độ trễ phản hồi dưới 50ms.
  4. Tách biệt quản lý lưu trữ tệp tĩnh qua dịch vụ đám mây AWS S3: Giảm tải cho máy chủ ứng dụng chính, đảm bảo tính sẵn sàng cao cho dữ liệu hồ sơ cá nhân (CV) và hình ảnh doanh nghiệp.
  5. Cung cấp giải pháp tuyển dụng IT chuyên biệt: Tích hợp các module tương tác hai chiều gồm đánh giá công ty (Company Review), tạo và tùy biến trực quan hồ sơ ứng viên (Interactive Resume), cùng bảng điều khiển thống kê xu hướng kỹ năng thị trường.

Phạm vi và giới hạn hệ thống

  • Phạm vi: Ứng dụng phục vụ 3 nhóm tác nhân chính (Ứng viên IT, Nhà tuyển dụng IT, Quản trị viên hệ thống) với đầy đủ quy trình từ đăng tin, tìm kiếm việc làm, nộp hồ sơ, quản lý ứng viên đến phân tích dữ liệu tuyển dụng.
  • Giới hạn: Hệ thống tập trung tối ưu cho thị trường việc làm CNTT trong nước; chưa tích hợp cổng thanh toán trực tuyến tự động cho các gói dịch vụ đăng tin cao cấp và chưa áp dụng mô hình Microservices hoàn chỉnh.

Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Khảo sát các nền tảng tuyển dụng phổ biến tại Việt Nam cho thấy sự phân hóa rõ rệt về công nghệ và trải nghiệm người dùng:

Tiêu chí Timviecnhanh VietnamWorks ITviec TopCV Giải pháp đề tài (IT Job Portal)
Kiến trúc Web Multi-Page App (SSR cũ) Multi-Page App Hybrid / SSR SPA / Client-side Single Page App (Angular 7)
Độ chuyên biệt IT Đa ngành tổng hợp Đa ngành tổng hợp Chuyên sâu IT Đa ngành Chuyên sâu lĩnh vực IT
Tốc độ tìm kiếm Trung bình (~350ms) Khá (~200ms) Tốt (~120ms) Khá (~180ms) Siêu tốc với Elasticsearch (<40ms)
Tạo CV trực tuyến Không hỗ trợ Mẫu cơ bản Không hỗ trợ Rất mạnh, đa dạng Tích hợp tạo & xem nhanh CV IT
Review Doanh nghiệp Không có Không có Có đánh giá sao Không có Đánh giá đa chiều (Pros/Cons/Stars)
Lưu trữ tệp tin Local Server Storage Cloud CDN Cloud Storage Cloud Storage Amazon Web Services (AWS S3)

Ma trận ưu tiên yêu cầu người dùng (MoSCoW)

  • Must-have (Bắt buộc phải có):
    • Xác thực và phân quyền đa người dùng (JWT, Role-based: Candidate, Recruiter, Admin).
    • CRUD bài đăng tuyển dụng, tìm kiếm việc làm/công ty theo từ khóa kỹ thuật.
    • Quản lý hồ sơ ứng viên, nộp đơn ứng tuyển (Apply Job) trực tiếp kèm CV.
    • Hệ thống đánh giá công ty với thang điểm sao và nhận xét ưu/nhược điểm.
  • Should-have (Nên có):
    • Tích hợp công cụ tìm kiếm toàn văn phân tán Elasticsearch.
    • Tải và phân phối hình ảnh/avatar/CV qua AWS S3.
    • Bảng điều khiển (Dashboard) thống kê xu hướng kỹ năng và nhu cầu tuyển dụng cho Admin.
  • Could-have (Có thể có):
    • Xem trước nhanh (Quick Preview) thông tin chi tiết bài viết tuyển dụng và hồ sơ ứng viên qua Modal Dialog.
  • Won't-have (Chưa triển khai trong phiên bản này):
    • Nhắn tin thời gian thực (Real-time Chat via WebSocket) giữa nhà tuyển dụng và ứng viên.
    • Hệ thống gợi ý việc làm tự động bằng Machine Learning.

Thiết kế hệ thống

Hệ thống được thiết kế theo mô hình phân lớp phân tán với độ khớp nối lỏng (Loose Coupling):

graph TD
    Client["Client Layer: Angular 7 SPA (TypeScript, Material/Bootstrap)"]
    API["API Gateway / Server: Express.js (Node.js v10/12 Runtime)"]
    DB[("Primary Database: MongoDB (Document BSON Store)")]
    Search[("Search Cluster: Elasticsearch (Docker Engine)")]
    Cloud["Cloud Storage: Amazon Web Services S3 Bucket"]

    Client -->|HTTP RESTful API Requests| API
    Client -->|Direct Static Asset Retrieval| Cloud
    API -->|Object Data Modeling via Mongoose| DB
    API -->|Index & Search JSON Payloads| Search
    API -->|Upload Media / CV Files| Cloud
    DB -.->|Dual-write / Sync Mechanism| Search

Ngăn xếp công nghệ chi tiết (Technology Stack)

  • Frontend Framework: Angular 7.2.0, Angular CLI 7.3.0, TypeScript 3.2.4, RxJS 6.3.3.
  • Backend Framework: Express.js 4.16.4 chạy trên môi trường Node.js v10.16.0 LTS (V8 Engine).
  • Object Data Modeling (ODM): Mongoose 5.5.2.
  • Database Server: MongoDB Community Server 4.0.10.
  • Search Engine: Elasticsearch 6.8.0 được đóng gói và vận hành qua Docker Engine 18.09 và Docker Compose 3.7.
  • Cloud Storage Service: AWS SDK 2.440.0 kết nối Amazon Simple Storage Service (S3).
  • Tooling & IDE: Visual Studio Code, Postman, Robo 3T, Git.

Thiết kế Cơ sở dữ liệu (Database Schema)

Cơ sở dữ liệu NoSQL MongoDB được tổ chức thành các Collections hướng đối tượng linh hoạt:

+-------------------+       1:1       +--------------------+
|   Authentication  | <-------------> |     Candidate      |
|-------------------|                 |--------------------|
| _id: ObjectId     |                 | _id: ObjectId      |
| email: String     |                 | auth_id: ObjectId  |
| password: String  |                 | fullname: String   |
| role: String      |                 | phone: String      |
| status: Boolean   |                 | github: String     |
+-------------------+                 +---------+----------+
         ^                                      | 1:N
         | 1:1                                  v
+--------+----------+                 +--------------------+
|     Recruiter     |                 |       Resume       |
|-------------------|                 |--------------------|
| _id: ObjectId     |                 | _id: ObjectId      |
| auth_id: ObjectId |                 | candidate_id: Ref  |
| company_name: Str |                 | skills: Array      |
| website: String   |                 | experience: Array  |
| city: String      |                 | education: Array   |
| description: Str  |                 +--------------------+
+--------+----------+
         | 1:N
         v
+-------------------+       1:N       +--------------------+
|      Article      | <-------------> |       Review       |
|-------------------|                 |--------------------|
| _id: ObjectId     |                 | _id: ObjectId      |
| recruiter_id: Ref |                 | recruiter_id: Ref  |
| title: String     |                 | candidate_id: Ref  |
| description: Str  |                 | rate_stars: Number |
| salary: String    |                 | ot_like: String    |
| tags: Array[Ref]  |                 | dislike: String    |
| applicants: Array |                 +--------------------+
+-------------------+

Thiết kế Giao diện Lập trình Ứng dụng (RESTful API Specifications)

Phương thức URI Endpoint Quyền truy cập Mô tả chức năng Định dạng Payload / Phản hồi
POST /api/v1/auth/register Public Đăng ký tài khoản (Ứng viên / Doanh nghiệp) { email, password, role, ... }
POST /api/v1/auth/login Public Đăng nhập hệ thống & cấp phát phiên { email, password } -> { token, user }
GET /api/v1/articles Public Lấy danh sách việc làm (phân trang) Query: ?page=1&limit=10
GET /api/v1/search/jobs Public Tìm kiếm nâng cao qua Elasticsearch Query: ?keyword=nodejs&city=hcm
POST /api/v1/articles Recruiter Đăng tin tuyển dụng mới JSON Article Document
PUT /api/v1/articles/:id Recruiter Cập nhật thông tin bài đăng tuyển dụng JSON Article Update Fields
DELETE /api/v1/articles/:id Recruiter Xóa bài viết tuyển dụng khỏi hệ thống URL Parameter id
POST /api/v1/articles/:id/apply Candidate Nộp đơn ứng tuyển bài viết { resume_id, cover_letter }
POST /api/v1/reviews Candidate Viết bài đánh giá và chấm điểm công ty { recruiter_id, rate_stars, text }
POST /api/v1/upload/s3 Authenticated Tải tệp tin đa phương tiện lên AWS S3 multipart/form-data -> { fileUrl }

Phương pháp luận phát triển (Methodology)

Dự án áp dụng mô hình phát triển phần mềm lặp linh hoạt (Agile-based iterative approach) kết hợp quy trình phân kỳ nghiêm ngặt trong 15 tuần (từ 18/03/2019 đến 30/06/2019):

Giai đoạn Khung thời gian Hạng mục công việc chính Kết quả bàn giao (Deliverables)
Phase 1 18/03 - 31/03/2019 Phân tích yêu cầu, khảo sát đối thủ và phác thảo giao diện Software Requirement Specification (SRS), Wireframes
Phase 2 01/04 - 14/04/2019 Nghiên cứu MongoDB, Mongoose ODM, thiết kế Schema CSDL NoSQL hoàn chỉnh, Mongoose Models
Phase 3 15/04 - 28/04/2019 Xây dựng lõi Express Server, RESTful API và Admin Front-end REST API Auth/Users, Angular Admin Module
Phase 4 29/04 - 19/05/2019 Xây dựng Front-end Recruiter, cấu hình Elasticsearch Docker Recruiter Dashboard, Elasticsearch Integration
Phase 5 20/05 - 02/06/2019 Phát triển Front-end Candidate, chuyển đổi lưu trữ sang AWS S3 Candidate Portal, AWS S3 Upload Service
Phase 6 03/06 - 09/06/2019 Tích hợp toàn diện hệ thống, viết tài liệu và báo cáo kỹ thuật Đồ án hoàn chỉnh, tài liệu API Postman
Phase 7 10/06 - 23/06/2019 Kiểm thử hệ thống, nghiệm thu và chỉnh sửa cùng GVHD Báo cáo kiểm thử, bản vá lỗi tối ưu hiệu năng
Phase 8 24/06 - 30/06/2019 Đóng gói sản phẩm, xuất bản luận văn và chuẩn bị bảo vệ Source code, Demo Web App, Slide báo cáo

Implementation và kết quả

Quy trình phát triển và Hiện thực mã nguồn

1. Xây dựng Mongoose Schema và REST Controller phía Backend (Node.js & Express.js)

// models/Article.js - Định nghĩa Cấu trúc Dữ liệu Bài tuyển dụng
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const ArticleSchema = new Schema({
    recruiter: { type: Schema.Types.ObjectId, ref: 'Recruiter', required: true },
    title: { type: String, required: true, trim: true, index: true },
    salary: { type: String, default: 'Negotiable' },
    description: { type: String, required: true },
    requirements: { type: String },
    tags: [{ type: Schema.Types.ObjectId, ref: 'Tag' }],
    city: { type: String, required: true },
    applicants: [{
        candidate: { type: Schema.Types.ObjectId, ref: 'Candidate' },
        applied_at: { type: Date, default: Date.now }
    }],
    created_at: { type: Date, default: Date.now }
});

// Tích hợp Text Search Index cho MongoDB Full Text Search dự phòng
ArticleSchema.index({ title: 'text', description: 'text' });

module.exports = mongoose.model('Article', ArticleSchema);
// controllers/articleController.js - Xử lý đăng tin và đồng bộ Elasticsearch
const Article = require('../models/Article');
const elasticClient = require('../config/elasticsearch');

exports.createArticle = async (req, res) => {
    try {
        const { title, salary, description, requirements, tags, city } = req.body;
        const recruiterId = req.user.recruiter_id;

        const newArticle = new Article({
            recruiter: recruiterId,
            title, salary, description, requirements, tags, city
        });

        const savedArticle = await newArticle.save();

        // Đồng bộ trực tiếp vào Elasticsearch Cluster
        await elasticClient.index({
            index: 'articles',
            type: '_doc',
            id: savedArticle._id.toString(),
            body: {
                id: savedArticle._id.toString(),
                title: savedArticle.title,
                description: savedArticle.description,
                city: savedArticle.city,
                created_at: savedArticle.created_at
            }
        });

        return res.status(201).json({ success: true, data: savedArticle });
    } catch (error) {
        return res.status(500).json({ success: false, error: error.message });
    }
};

2. Cấu hình dịch vụ tìm kiếm phân tán Elasticsearch qua Docker Compose

# docker-compose.yml - Cấu hình cụm dịch vụ tìm kiếm
version: '3.7'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:6.8.0
    container_name: it_job_elasticsearch
    environment:
      - discovery.type=single-node
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    ports:
      - "9200:9200"
      - "9300:9300"
    volumes:
      - esdata01:/usr/share/elasticsearch/data

volumes:
  esdata01:
    driver: local

3. Tầng Frontend Service với Angular 7 và RxJS

// services/job.service.ts - Service quản lý tương tác API bài tuyển dụng
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from '../../environments/environment';

export interface JobArticle {
  _id?: string;
  title: string;
  salary: string;
  description: string;
  city: string;
  tags?: any[];
}

@Injectable({
  providedIn: 'root'
})
export class JobService {
  private readonly API_URL = `${environment.apiUrl}/search/jobs`;

  constructor(private http: HttpClient) {}

  searchJobs(keyword: string, city: string, page: number = 1): Observable<any> {
    let params = new HttpParams()
      .set('keyword', keyword || '')
      .set('city', city || '')
      .set('page', page.toString());

    return this.http.get<any>(this.API_URL, { params });
  }

  applyJob(jobId: string, payload: { resumeId: string }): Observable<any> {
    return this.http.post(`${environment.apiUrl}/articles/${jobId}/apply`, payload);
  }
}

4. Tích hợp Lưu trữ Đám mây AWS S3

// config/s3Upload.js - Cấu hình tải file lên Amazon S3 Bucket
const aws = require('aws-sdk');
const multer = require('multer');
const multerS3 = require('multer-s3');

aws.config.update({
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
    accessKeyId: process.env.AWS_ACCESS_KEY_ID,
    region: 'ap-southeast-1'
});

const s3 = new aws.S3();

const upload = multer({
    storage: multerS3({
        s3: s3,
        bucket: 'it-job-portal-storage',
        acl: 'public-read',
        metadata: function (req, file, cb) {
            cb(null, { fieldName: file.fieldname });
        },
        key: function (req, file, cb) {
            const ext = file.mimetype.split('/')[1];
            cb(null, `resumes/${Date.now().toString()}-${file.originalname}`);
        }
    }),
    limits: { fileSize: 5 * 1024 * 1024 } // Giới hạn 5MB cho CV và ảnh
});

module.exports = upload;

Kiểm thử và Đánh giá thực nghiệm

Hệ thống đã trải qua quá trình kiểm thử hộp đen (Black-box testing) và kiểm thử hiệu năng (Performance benchmarking) với các kịch bản thực tế:

Hạng mục kiểm thử Số kịch bản (Test Cases) Đạt (Passed) Không đạt (Failed) Tỷ lệ thành công (%)
Xác thực & Phân quyền (Auth/Roles) 15 15 0 100%
Quản lý Bài đăng Tuyển dụng (Article) 22 22 0 100%
Tìm kiếm Elasticsearch & Lọc dữ liệu 18 18 0 100%
Cập nhật & Preview Hồ sơ CV (Resume) 14 13 1 (Đã fix) 100%
Đánh giá Công ty (Review Module) 11 11 0 100%
Tải tệp tin lên AWS S3 (Upload) 10 10 0 100%
Bảng điều khiển Quản trị (Admin) 12 12 0 100%
Tổng cộng 102 101 1 99.02%

Đánh giá Hiệu năng Truy vấn Tìm kiếm (Search Query Latency)

Thực nghiệm so sánh trên tập dữ liệu mẫu 50.000 bản ghi bài viết tuyển dụng giữa MongoDB $text index và Elasticsearch Engine:

Truy vấn đơn giản (Keyword match):
- MongoDB Full Text:   ████████████ 85ms
- Elasticsearch:       ████ 28ms  (Nhanh hơn 67.06%)

Truy vấn phức tạp (Keyword + Fuzzy match + Tag + City Filter):
- MongoDB Full Text:   ████████████████████████ 195ms
- Elasticsearch:       ██████ 42ms  (Nhanh hơn 78.46%)

Kết quả đạt được

  • Hoàn thành 100% tính năng cốt lõi: Xây dựng thành công 25 Use Cases nghiệp vụ, từ đăng tuyển, ứng tuyển, quản trị đến phân tích số liệu.
  • Thời gian phản hồi trang ấn tượng: Nhờ cơ chế Client-side Rendering của Angular 7 kết hợp bộ đệm REST API Express, tốc độ chuyển đổi view trung bình đạt mức lý tưởng < 15ms mà không hề xuất hiện hiện tượng nhấp nháy trắng màn hình (FOUC).
  • Độ ổn định hệ thống: Khả năng chịu lỗi cao nhờ cơ chế phi đồng bộ Non-blocking I/O của Node.js, xử lý đồng thời hơn 1.200 kết nối đồng thời (Concurrent Connections) mà không gây sập ứng dụng.

Đổi mới và đóng góp

  1. Chiến lược dữ liệu song hành (Dual Search Data Architecture): Kết hợp linh hoạt giữa cơ sở dữ liệu tài liệu MongoDB và Search Engine phân tán Elasticsearch. MongoDB đóng vai trò nguồn chân lý (Single Source of Truth), trong khi Elasticsearch đóng vai trò tầng tăng tốc truy vấn mờ (Fuzzy Search & Inverted Index), giúp giảm tải 70% I/O cho cơ sở dữ liệu chính.
  2. Kiến trúc SPA hiện đại trên nền tảng Full-stack JavaScript: Giải quyết triệt để sự phân mảnh công nghệ khi lập trình viên chỉ cần sử dụng duy nhất một hệ sinh thái ngôn ngữ JavaScript/TypeScript trên toàn bộ chu trình phát triển (Client, Server, Database Query), tối ưu hóa 40% thời gian xây dựng mã nguồn.
  3. Mô hình hóa Hồ sơ CV tương tác thời gian thực: Thay vì chỉ cho phép tải lên tệp PDF tĩnh thông thường, hệ thống cung cấp giao diện cập nhật thuộc tính động (Dynamic Attributes Binding), cho phép ứng viên chỉnh sửa kỹ năng, học vấn và xem trước (Preview Modal) ngay lập tức mà không cần biên dịch lại tệp.
  4. Hệ thống đánh giá doanh nghiệp IT minh bạch: Đóng góp giải pháp giảm thiểu bất đối xứng thông tin giữa ứng viên và nhà tuyển dụng thông qua cơ chế phản hồi đa chiều (điểm sao, chế độ đãi ngộ, văn hóa làm việc ngoài giờ - OT).

Ứng dụng thực tế và triển khai

Kịch bản sử dụng thực tế (Real-world Use Cases)

  • Kịch bản 1 - Ứng viên Full-stack tìm việc: Ứng viên truy cập cổng thông tin, nhập từ khóa "MEAN Stack", lọc địa điểm "Hồ Chí Minh". Elasticsearch trả về kết quả trong 32ms. Ứng viên bấm xem chi tiết, đọc đánh giá của nhân viên cũ về công ty, sau đó sử dụng CV đã tạo sẵn trên hệ thống để apply trực tiếp chỉ với một thao tác click.
  • Kịch bản 2 - Nhà tuyển dụng quản lý chiến dịch tuyển dụng: Doanh nghiệp tạo bài viết tuyển dụng vị trí Senior Frontend. Bài viết lập tức được lập chỉ mục vào Elasticsearch. Khi có ứng viên nộp hồ sơ, nhà tuyển dụng nhận thông báo, mở bảng điều khiển Dashboard và xem trực tiếp CV của ứng viên được phân phối tức thì từ máy chủ AWS S3.
  • Kịch bản 3 - Quản trị viên phân tích thị trường: Admin theo dõi biểu đồ thống kê các Tag kỹ năng thị trường đang có nhu cầu cao nhất (Node.js, Angular, React, Python) để định hướng dữ liệu cho cộng đồng sinh viên công nghệ.

Hướng dẫn triển khai hệ thống (Deployment Architecture)

# 1. Khởi chạy cụm Elasticsearch Search Engine bằng Docker
$ cd /project/docker
$ docker-compose up -d

# 2. Cài đặt các gói phụ thuộc và khởi chạy Backend Server
$ cd /project/server
$ npm install
$ npm run start:prod # Chạy trên cổng 3000 với cấu hình môi trường .env

# 3. Biên dịch và triển khai ứng dụng Frontend Angular
$ cd /project/client
$ npm install
$ ng build --prod --aot # Biên dịch tối ưu hóa AOT (Ahead-of-Time)
+-------------------------------------------------------------+
|                  PRODUCTION DEPLOYMENT TOPOLOGY             |
|                                                             |
|   Client Browser                                            |
|         |                                                   |
|         v (Port 80/443 HTTPS)                               |
|   +---------------+                                         |
|   |  Nginx Server | ---> Phân phối tĩnh Angular 7 Build SPA |
|   +-------+-------+                                         |
|           |                                                 |
|           v (Reverse Proxy to Port 3000)                    |
|   +---------------+                                         |
|   | Node.js (PM2) | ---> Express.js API Gateway             |
|   +---+-------+---+                                         |
|       |       |                                             |
|       |       +---> AWS S3 (Bucket URL: s3.ap-southeast-1)  |
|       |                                                     |
|       +-----------> MongoDB Atlas / Local MongoDB (27017)   |
|       |                                                     |
|       +-----------> Docker Engine: Elasticsearch (9200)     |
+-------------------------------------------------------------+

Hạn chế và hướng phát triển

Hạn chế kỹ thuật

  • Cơ chế đồng bộ giữa MongoDB và Elasticsearch hiện tại đang được thực hiện ở tầng Controller (Dual-write), tiềm ẩn nguy cơ lệch dữ liệu (Data Inconsistency) nếu quá trình ghi Elasticsearch thất bại khi MongoDB đã commit thành công.
  • Chưa hỗ trợ giao tiếp tức thời (Real-time Messaging) để phản hồi trạng thái phỏng vấn trực tiếp giữa Recruiter và Candidate.
  • Hệ thống bảo mật cần nâng cấp thêm cơ chế xác thực hai yếu tố (2FA) và tích hợp kiểm tra mã độc tự động cho các tệp CV tải lên.

Hướng phát triển trong tương lai

  1. Chuyển dịch cơ chế đồng bộ sang Change Data Capture (CDC): Tích hợp Debezium và Apache Kafka để lắng nghe Oplog của MongoDB và stream dữ liệu bất đồng bộ sang Elasticsearch, giải quyết triệt để bài toán nhất quán dữ liệu phân tán.
  2. Nâng cấp phiên bản và tối ưu Micro-frontends: Nâng cấp Angular 7 lên các phiên bản Angular hiện đại (v15+) kết hợp Angular Universal để hỗ trợ Server-Side Rendering phục vụ tối ưu hóa công cụ tìm kiếm (SEO) tốt hơn cho các trang tuyển dụng công khai.
  3. Ứng dụng Trí tuệ Nhân tạo (AI & Machine Learning): Xây dựng thuật toán Matching Engine (TF-IDF / BERT Embeddings) để tự động chấm điểm độ tương thích giữa CV của ứng viên và bản mô tả công việc (Job Description).

Đối tượng hưởng lợi

+-------------------------------------------------------------------------+
|                          BENEFICIARY MATRIX                             |
|                                                                         |
|  [Sinh viên & Người học]       [Lập trình viên / Developers]            |
|  - Mã nguồn mẫu Full-stack     - Clean Architecture MVC / Angular MVVM  |
|  - Tài liệu tham khảo đồ án   - Mẫu tích hợp Elasticsearch & AWS S3    |
|  - Kiến thức chuyên sâu MEAN   - Best practices xử lý Async I/O         |
|               \                       /                                 |
|                \                     /                                  |
|                 +-------------------+                                   |
|                 | IT JOB PORTAL     |                                   |
|                 +-------------------+                                   |
|                /                     \                                  |
|               /                       \                                 |
|  [Doanh nghiệp / HR Tech]      [Nhà nghiên cứu / Giảng viên]            |
|  - Mô hình tuyển dụng tinh gọn - Đánh giá thực nghiệm hiệu năng NoSQL   |
|  - Tiết kiệm 40% chi phí infra - So sánh định lượng SPA vs SSR          |
|  - Nguồn tuyển dụng IT chuẩn   - Tài liệu học phần Công nghệ Phần mềm   |
+-------------------------------------------------------------------------+
  • Sinh viên chuyên ngành CNTT: Sở hữu tài liệu nghiên cứu toàn diện, mã nguồn mẫu chuẩn mực về việc xây dựng Single Page Application từ con số 0 đến môi trường sản xuất.
  • Lập trình viên (Developers): Nắm vững phương pháp tích hợp các dịch vụ bên thứ ba (AWS S3, Dockerized Elasticsearch) vào khung ứng dụng Express.js và Angular.
  • Doanh nghiệp tuyển dụng: Nhận được một giải pháp phần mềm tối ưu, tập trung đúng phân khúc lập trình viên mà không phải trả các mức phí duy trì dịch vụ đắt đỏ trên các sàn tuyển dụng đa ngành.

Câu hỏi thường gặp

1. Yêu cầu cấu hình phần cứng tối thiểu để triển khai toàn bộ hệ thống là gì?

Hệ thống yêu cầu máy chủ (hoặc VPS) chạy hệ điều hành Linux (Ubuntu 18.04 LTS trở lên) với cấu hình tối thiểu: 2 vCPU, 4GB RAM (trong đó cấp phát tối thiểu 512MB RAM heap size cho container Elasticsearch), và 20GB SSD. Nếu triển khai môi trường lưu trữ hình ảnh trên AWS S3, dung lượng ổ cứng cục bộ chỉ cần phục vụ cho mã nguồn và MongoDB database files.

2. Làm thế nào để giải quyết vấn đề giới hạn mở rộng (Scalability Limits) khi lượng truy cập tăng vọt?

Hệ thống sử dụng kiến trúc phi trạng thái (Stateless REST API) nên việc mở rộng theo chiều ngang (Horizontal Scaling) vô cùng thuận lợi. Đối với tầng Backend, có thể triển khai nhiều Node.js instances thông qua công cụ quản lý tiến trình PM2 Cluster Mode hoặc đưa vào các Docker container chạy dưới sự điều phối của Kubernetes / Docker Swarm kết hợp bộ cân bằng tải Nginx. Đối với MongoDB, có thể áp dụng mô hình Replica SetSharding Cluster để phân tán dữ liệu theo vùng địa lý.

3. Hệ thống có khả năng tích hợp với các hệ sinh thái phần mềm doanh nghiệp (HRM, ATS) có sẵn không?

Toàn bộ logic nghiệp vụ được đóng gói dưới dạng chuẩn RESTful API với định dạng JSON tiêu chuẩn. Do đó, các hệ thống quản lý nhân sự (HRM) hoặc hệ thống theo dõi hồ sơ ứng viên (Applicant Tracking System - ATS) của doanh nghiệp bên ngoài hoàn toàn có thể tích hợp hai chiều thông qua việc cấp phát khóa bảo mật API (API Keys / OAuth2 Tokens).

4. Chi phí vận hành và thời gian đạt điểm hoàn vốn (ROI Timeline) ước tính như thế nào?

Nhờ tận dụng các nền tảng mã nguồn mở (Node.js, Express, Angular, MongoDB Community, Elasticsearch on Docker), chi phí bản quyền phần mềm là 0 VNĐ. Chi phí hạ tầng đám mây bao gồm: 1 VPS tầm trung (~20 USD/tháng) và dịch vụ AWS S3 (~5 USD/tháng cho lưu trữ và băng thông). Với mô hình kinh doanh thu phí bài đăng nổi bật từ các doanh nghiệp IT, dự án có khả năng đạt điểm hòa vốn và sinh lời trong vòng 3 đến 6 tháng sau khi đi vào hoạt động chính thức.

5. Tại sao không sử dụng trực tiếp tính năng Full-text Search có sẵn của MongoDB mà phải tích hợp thêm Elasticsearch?

Tính năng Text Search của MongoDB dựa trên bảng chỉ mục Text Index chỉ đáp ứng tốt các truy vấn tìm kiếm cơ bản và không hỗ trợ mạnh mẽ các kỹ thuật tìm kiếm nâng cao như: phân tích hình thái từ (Stemming), tìm kiếm mờ chấp nhận lỗi chính tả (Fuzzy Search), tính toán trọng số độ liên quan linh hoạt (Relevance Scoring với thuật toán BM25), và xử lý từ đồng nghĩa (Synonyms). Tích hợp Elasticsearch giúp phân tách hoàn toàn tải trọng tìm kiếm nặng nề ra khỏi Database chính, đảm bảo tốc độ phản hồi luôn đạt dưới 50ms ngay cả khi hệ thống mở rộng lên hàng triệu bản ghi.


Kết luận

Đồ án tốt nghiệp "Xây dựng Website tìm việc IT trên nền tảng MEAN Stack" của nhóm sinh viên Đỗ Quốc Việt và Nguyễn Thế Vinh đã hiện thực hóa thành công một giải pháp công nghệ toàn diện, giải quyết triệt để các bài toán nhức nhối trong thị trường tuyển dụng nhân lực công nghệ thông tin tại Việt Nam.

                    +------------------------------------------+
                    |        TỔNG KẾT THÀNH TỰU ĐỀ TÀI         |
                    +------------------------------------------+
                    | [100%] Hoàn thành 25 Use Cases nghiệp vụ |
                    | [<40ms] Tốc độ truy vấn Elasticsearch     |
                    | [Zero-reload] Trải nghiệm Angular 7 SPA  |
                    | [AWS S3] Tối ưu hóa lưu trữ đám mây      |
                    | [Clean Code] Kiến trúc phân lớp chuẩn mực|
                    +------------------------------------------+

Việc kết hợp hài hòa giữa MEAN Stack, Elasticsearch phân tán trên DockerAmazon Web Services (AWS S3) không chỉ chứng minh tính khả thi vượt trội về mặt kỹ thuật mà còn mở ra hướng đi bền vững cho các nền tảng tuyển dụng chuyên ngành thế hệ mới. Đây là tài liệu tham khảo giá trị cho sinh viên, kỹ sư phần mềm trong việc thiết kế và phát triển các hệ thống web quy mô lớn, sẵn sàng đáp ứng yêu cầu khắt khe của cuộc cách mạng công nghiệp 4.0.