const mongoose = require('mongoose'); const blogSchema = new mongoose.Schema({ // Basic blog information title: { type: String, required: true, trim: true }, slug: { type: String, required: true, unique: true, trim: true }, excerpt: { type: String, required: true, maxlength: 500 }, content: { type: mongoose.Schema.Types.Mixed, // Có thể là string HTML hoặc JSON EditorJS required: true }, // Media featuredImage: { type: String, default: '' }, galleryImages: [{ type: String }], // Mảng URL ảnh cho gallery (details-2, details-3) // Author and publishing author: { type: String, default: 'Admin' }, publishedAt: { type: String, // Format: "11 March 2025" default: function() { return new Date().toLocaleDateString('en-GB', { day: 'numeric', month: 'long', year: 'numeric' }); } }, // Categorization (simple strings, no references) category: [{ type: String // ["Visa", "Travel", ...] - Một bài có thể thuộc nhiều category }], tags: [{ type: String // ["WorkVisa", "StudentVisa", ...] }], // Status and features status: { type: String, enum: ['draft', 'published'], default: 'published' }, isFeatured: { type: Boolean, default: false }, // Comments count (có thể fake trước) commentsCount: { type: Number, default: 0 }, // Quote/Sidebar section quote: { type: String, default: '', trim: true }, // Content after quote contentAfterQuote: { type: String, default: '', trim: true } }, { timestamps: true }); // Indexes blogSchema.index({ slug: 1 }); blogSchema.index({ status: 1, createdAt: -1 }); blogSchema.index({ category: 1, status: 1 }); blogSchema.index({ isFeatured: 1, status: 1 }); blogSchema.index({ tags: 1, status: 1 }); // Remove __v from JSON output blogSchema.set('toJSON', { transform: function(doc, ret) { delete ret.__v; return ret; } }); // Pre-save middleware blogSchema.pre('save', function(next) { // Auto-generate slug if not provided if (!this.slug && this.title) { this.slug = this.title .toLowerCase() .replace(/[^a-z0-9\s-]/g, '') .replace(/\s+/g, '-') .replace(/-+/g, '-') .trim('-'); } next(); }); // Static methods blogSchema.statics.getPublished = function() { return this.find({ status: 'published' }).sort({ createdAt: -1 }); }; blogSchema.statics.getFeatured = function() { return this.find({ status: 'published', isFeatured: true }).sort({ createdAt: -1 }); }; blogSchema.statics.getByCategory = function(category) { return this.find({ status: 'published', category: { $in: [category] } // Tìm trong array categories }).sort({ createdAt: -1 }); }; blogSchema.statics.getByTag = function(tag) { return this.find({ status: 'published', tags: tag }).sort({ createdAt: -1 }); }; module.exports = mongoose.model('Blog', blogSchema);