{"id":3647,"date":"2025-10-08T07:10:55","date_gmt":"2025-10-08T04:10:55","guid":{"rendered":"https:\/\/shedov.top\/ru\/?p=3647"},"modified":"2026-03-15T23:37:05","modified_gmt":"2026-03-15T20:37:05","slug":"simulyaciya-funkcionirovaniya-crystal-v2-0","status":"publish","type":"post","link":"https:\/\/shedov.top\/ru\/simulyaciya-funkcionirovaniya-crystal-v2-0\/","title":{"rendered":"\ud83d\udc8e \u0414\u043d\u0435\u0432\u043d\u0438\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 CRYSTAL #1: \u0421\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f CRYSTAL v2.0 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c turboMaker \u0438 superMaker"},"content":{"rendered":"<div class=\"single_contents\">\n<h2>\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435:<\/h2>\n<nav>\n<ul>\n<li>1. <a href=\"#paragraph_1\">\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/a><\/li>\n<li>2. <a href=\"#paragraph_2\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 npm \u043f\u0430\u043a\u0435\u0442\u043e\u0432<\/a><\/li>\n<li>3. <a href=\"#paragraph_3\">\u0412\u0438\u0434\u0435\u043e \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f CRYSTAL v2.0<\/a><\/li>\n<li>4. <a href=\"#paragraph_4\">\u0410\u043d\u0430\u043b\u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/a><\/li>\n<li>5. <a href=\"#paragraph_5\">\u041d\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432<\/a><\/li>\n<li>6. <a href=\"#paragraph_6\">\u041f\u043b\u0430\u043d\u044b \u043f\u043e \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c\u0443 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/a><\/li>\n<\/ul>\n<\/nav>\n<\/div>\n\n<h2 id=\"paragraph_1\">1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n\n<p>\u0421\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043f\u043e\u0441\u0442\u043e\u0432, \u043b\u0430\u0439\u043a\u043e\u0432, \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432 \u0438 \u0442.\u0434.<\/p>\n \n<p>\u0426\u0435\u043b\u044c \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 \u0438 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u0432\u044b\u0441\u043e\u043a\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0443\u0440\u043e\u0432\u043d\u044f\u0445:<\/p>\n\n<ul>\n<li><strong>\u2014 \u0418\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430:<\/strong> VPC, Nginx.<\/li>\n<li><strong>\u2014 \u0421\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c:<\/strong> backend \u0438 \u0431\u0430\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<\/li>\n<li><strong>\u2014 \u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c:<\/strong> frontend.<\/li>\n<\/ul>\n\n<h2 id=\"paragraph_2\">2. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 npm \u043f\u0430\u043a\u0435\u0442\u043e\u0432<\/h2>\n\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438, \u043c\u043d\u043e\u0439 \u0431\u044b\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u044b 4 npm \u043f\u0430\u043a\u0435\u0442\u0430 \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e:<\/p>\n\n<p><a href=\"https:\/\/www.npmjs.com\/package\/turbo-maker\" target=\"_blank\" rel=\"noopener\"><strong>turboMaker<\/strong><\/a><\/p>\n<p>\u0421\u0443\u043f\u0435\u0440\u0431\u044b\u0441\u0442\u0440\u044b\u0439, \u043c\u043d\u043e\u0433\u043e\u043f\u043e\u0442\u043e\u0447\u043d\u044b\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f MongoDB, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 CLI. \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0432\u0441\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 CPU.<\/p>\n\n<p><a href=\"https:\/\/www.npmjs.com\/package\/super-maker\" target=\"_blank\" rel=\"noopener\"><strong>superMaker<\/strong><\/a><\/p>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f turboMaker. \u0413\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435: <code class=\"inline-code\">\u0442\u0435\u043a\u0441\u0442<\/code>, <code class=\"inline-code\">\u0445\u0435\u0448\u0442\u0435\u0433\u0438<\/code>, <code class=\"inline-code\">\u0441\u043b\u043e\u0432\u0430<\/code>, <code class=\"inline-code\">email<\/code>, <code class=\"inline-code\">id<\/code>, <code class=\"inline-code\">url<\/code>, <code class=\"inline-code\">array<\/code>, <code class=\"inline-code\">boolean<\/code> \u0438 \u0442.\u0434.<\/p>\n\n<p><a href=\"https:\/\/www.npmjs.com\/package\/mongo-collector\" target=\"_blank\" rel=\"noopener\"><strong>mongoCollector<\/strong><\/a><\/p>\n<p>CLI \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0438\u0437 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 MongoDB \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0445 \u0432 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438.<\/p>\n\n<p><a href=\"https:\/\/www.npmjs.com\/package\/mongo-checker\" target=\"_blank\" rel=\"noopener\"><strong>mongoChecker<\/strong><\/a><\/p>\n<p>CLI \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u043f\u043e\u0438\u0441\u043a\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0445\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 MongoDB \u043f\u043e \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u043e\u043b\u044e.<\/p>\n\n<h2 id=\"paragraph_3\">3. \u0412\u0438\u0434\u0435\u043e \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f CRYSTAL v2.0<\/h2>\n\n\n<div class=\"single_external_video\">\n   <iframe src=\"https:\/\/vk.com\/video_ext.php?oid=-161152224&id=456239081&hd=2&amp;autoplay=0\" allow=\"autoplay; encrypted-media; fullscreen; picture-in-picture; screen-wake-lock;\" style=\"border:0;\" allowfullscreen=\"\"><\/iframe>\n<\/div>\n\n<h2 id=\"paragraph_4\">4. \u0410\u043d\u0430\u043b\u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/h2>\n\n<p>\u0412 \u0446\u0435\u043b\u043e\u043c, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 1,000,000 \u043f\u043e\u0441\u0442\u043e\u0432, \u043f\u043e\u043a\u0430\u0437\u0430\u043b\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0432\u0441\u0435\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u0443\u044e \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0443 \u043f\u043e\u0441\u0442\u043e\u0432 \u0432 infinite scroll.<\/p>\n<p>\u041d\u043e \u043a\u0430\u043a \u0438 \u043e\u0436\u0438\u0434\u0430\u043b\u043e\u0441\u044c, \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u043f\u0438\u0441\u043a\u0430 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432 (\u0410\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043c\u044b), \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0439 \u0438\u0437-\u0437\u0430 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0438\u0437\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u044f \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u044b\u043b\u0430 \u0432\u044b\u0431\u0440\u0430\u043d\u0430 \u0434\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 \u0440\u0430\u043d\u043d\u0438\u0445 \u044d\u0442\u0430\u043f\u0430\u0445.<\/p>\n\n<p>\u0414\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0445 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432, \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043e\u0431\u0445\u043e\u0434 \u0432\u0441\u0435\u0445 \u043f\u043e\u0441\u0442\u043e\u0432 \u0447\u0435\u0440\u0435\u0437 \u0430\u0433\u0440\u0435\u0433\u0430\u0446\u0438\u044e (<code class=\"inline-code\">$unwind<\/code>, <code class=\"inline-code\">$group<\/code>), \u0447\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0437\u0430\u043c\u0435\u0434\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438:<\/p>\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">hashtag.controller.js<\/h2>\n\n\n<pre class=\"wp-block-code lang-js line-numbers\"><code>import { PostModel } from \"..\/..\/modules\/post\/index.js\";\nimport {\n    handleServerError\n} from \"..\/..\/shared\/helpers\/index.js\";\n\nexport const getHashtags = async (req, res) => {\n    const { limit } = req.query;\n    const max = parseInt(limit) || 6;\n    let result = await PostModel.aggregate([\n        {\n            $unwind: \"$hashtags\"\n        },\n        {\n            $group: {\n                _id: \"$hashtags\",\n                \"hashtag\": {\n                    $first: \"$hashtags\"\n                },\n                \"numberPosts\": {\n                    $sum: 1\n                }\n            }\n        },\n        {\n            $sort: {\n                \"numberPosts\": -1,\n                \"hashtag\": 1\n            }\n        },\n        {\n            $project: {\n                \"_id\": false\n            }\n        }\n    ]).collation({ locale: 'en', strength: 2 }).limit(max).exec();\n    try {\n        return res.status(200).json(result);\n    } catch (error) {\n        handleServerError(res, error);\n    }\n};\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">post.model.js<\/h2>\n\n\n<pre class=\"wp-block-code lang-js line-numbers\"><code>import mongoose from 'mongoose';\nconst PostSchema = new mongoose.Schema(\n  {\n    title: {\n      type: String,\n      default: ''\n    },\n    text: {\n      type: String,\n      default: ''\n    },\n    mainImageUri: String,\n    hashtags: {\n      type: Array,\n      default: [],\n    },\n    liked: {\n      type: Array,\n      default: [],\n    },\n    views: {\n      type: Number,\n      default: 0,\n    },\n    user: {\n      type: mongoose.Schema.Types.ObjectId,\n      ref: 'User',\n      required: true,\n    },\n  },\n  {\n    timestamps: true,\n  },\n);\n\nPostSchema.index({ createdAt: -1 });\n\nexport const PostModel = mongoose.model(\"Post\", PostSchema);\n<\/code><\/pre>\n\n\n<h2 id=\"paragraph_5\">5. \u041d\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432<\/h2>\n\n<p>\u0414\u043b\u044f \u0443\u0441\u043a\u043e\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432, \u0431\u044b\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0430 \u043d\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430, \u0438 \u0442\u0435\u043f\u0435\u0440\u044c \u0445\u0435\u0448\u0442\u0435\u0433\u0438 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c\u0441\u044f \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u2014 <code class=\"inline-code\">hashtags<\/code>:<\/p>\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">hashtag.model.js<\/h2>\n\n\n<pre class=\"wp-block-code lang-js line-numbers\"><code>import mongoose from 'mongoose';\n\nconst HashtagSchema = new mongoose.Schema(\n  {\n    name: {\n      type: String,\n      required: true,\n      trim: true,\n      lowercase: true,\n    },\n    postId: {\n      type: mongoose.Schema.Types.ObjectId,\n      ref: 'Post',\n      required: true,\n    },\n    postCreatedAt: {\n      type: Date,\n      required: true,\n    },\n  },\n  {\n    timestamps: true,\n  }\n);\n\nHashtagSchema.index({ name: 1, postCreatedAt: -1, postId: 1 }, { unique: true, collation: { locale: 'en', strength: 2 } }); \nHashtagSchema.index({ name: 1 });\nHashtagSchema.index({ postId: 1 });\n\nexport const HashtagModel = mongoose.model('Hashtag', HashtagSchema);\n<\/code><\/pre>\n \n\n<p><strong>\u0418\u043d\u0434\u0435\u043a\u0441\u044b:<\/strong><\/p>\n\n<p>1. <code class=\"inline-code\">index({ name: 1, postCreatedAt: -1, postId: 1 }, { unique: true, collation: { locale: 'en', strength: 2 } });<\/code><\/p>\n<p>\u2014 <strong>compound index<\/strong> \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043f\u043e\u0438\u0441\u043a\u0430 \u0438 \u043a\u0443\u0440\u0441\u043e\u0440\u043d\u043e\u0439 \u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u0438.<\/p>\n\n<p>2. <code class=\"inline-code\">index({ name: 1 });<\/code><\/p>\n<p>\u2014 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043e\u0431\u0449\u0435\u0433\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u043e\u0441\u0442\u043e\u0432 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u043c (aggregation stage).<\/p>\n\n<p>3. <code class=\"inline-code\">index({ postId: 1 });<\/code><\/p>\n<p>\u2014 \u0434\u043b\u044f \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432 \u043f\u043e\u0441\u0442\u0430.<\/p>\n\n<p><strong>\u0412\u044b\u0432\u043e\u0434 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u2014 '\u0410\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u043c\u044b':<\/strong><\/p>\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">hashtag.controller.js<\/h2>\n\n\n<pre class=\"wp-block-code lang-js line-numbers\"><code>import { HashtagModel } from '.\/hashtag.model.js';\nimport { handleServerError } from '..\/..\/shared\/helpers\/index.js';\n \nexport const getHashtags = async (req, res) => {\n  try {\n    const limit = parseInt(req.query.limit) || 6;\n\n    const result = await HashtagModel.aggregate([\n      \/\/ 1. \u0413\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0430 \u0438 \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u043f\u043e\u0441\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0445\u0435\u0448\u0442\u0435\u0433\u0430\n      { $group: { _id: \"$name\", quantity: { $count: {} } } },\n      \n      \/\/ 2. \u0421\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430: \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 (DESC), \u0437\u0430\u0442\u0435\u043c \u043f\u043e \u0438\u043c\u0435\u043d\u0438 (ASC)\n      { $sort: { quantity: -1, _id: 1 } }, \n      \n      \/\/ 3. \u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u043e\u0431\u0449\u0435\u0433\u043e \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\n      { $limit: limit }, \n\n      \/\/ 4. \u041f\u0440\u043e\u0435\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u0444\u043e\u0440\u043c\u0430\u0442\n      { $project: { name: \"$_id\", quantity: \"$quantity\", _id: 0 } }\n    ]);\n\n    return res.status(200).json(result);\n  } catch (error) {\n    handleServerError(res, error);\n  }\n};\n<\/code><\/pre>\n \n\n<p><strong>\u0412\u044b\u0432\u043e\u0434 \u043f\u043e\u0441\u0442\u043e\u0432 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u043c, \u0438 infinite scroll, \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0442 \u0441 \u043a\u0443\u0440\u0441\u043e\u0440\u043d\u043e\u0439 \u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u0435\u0439, \u0447\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e\u0441\u0442\u043e\u0432, \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 offset-\u043f\u0430\u0433\u0438\u043d\u0430\u0446\u0438\u0435\u0439, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438 \u0433\u043b\u0443\u0431\u043e\u043a\u043e\u0439 \u043f\u0440\u043e\u043a\u0440\u0443\u0442\u043a\u0435:<\/strong><\/p>\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">post.controller.js<\/h2>\n\n\n<pre class=\"wp-block-code lang-js line-numbers\"><code>export const getPostsByHashtag = async (req, res) => {\n  try {\n    const limit = parseInt(req.query.limit) || 10;\n    const hashtag = req.query.tag.toLowerCase();\n\n    \/\/ 1. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 ID (\u0431\u044b\u0441\u0442\u0440\u044b\u0439 find \u0441 \u0438\u043d\u0434\u0435\u043a\u0441\u043e\u043c)\n    let hashtagQuery = { name: hashtag };\n    if (req.query.cursor) {\n      const cursorDate = new Date(req.query.cursor);\n      if (isNaN(cursorDate.getTime())) {\n        return res.status(400).json({ message: 'Invalid cursor date' });\n      }\n      hashtagQuery.postCreatedAt = { $lt: cursorDate };\n    }\n\n    const hashtagDocs = await HashtagModel.find(hashtagQuery)\n      .sort({ postCreatedAt: -1 })\n      .limit(limit)\n      .select('postId postCreatedAt')\n      .lean()\n      .exec();\n\n    const postIds = hashtagDocs.map(doc => doc.postId);\n\n    if (postIds.length === 0) {\n      return res.status(200).json({ posts: [], nextCursor: null });\n    }\n\n    \/\/ 2. \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043a\u0430\u0440\u0442\u044b \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f (ID \u2192 \u0438\u043d\u0434\u0435\u043a\u0441) \u0434\u043b\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438\n    const idToIndexMap = new Map();\n    postIds.forEach((id, index) => idToIndexMap.set(id.toString(), index));\n\n    \/\/ 3. \u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0433\u043e \u0438 \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e '$in' \u043d\u0430 PostModel (unordered)\n    const fetchedPosts = await PostModel.find({ _id: { $in: postIds } })\n      .populate({\n        path: 'user',\n        select: ['name', 'customId', 'bio', 'status', 'creator', 'avatar', 'createdAt', 'updatedAt'],\n      })\n      .exec();\n      \n    \/\/ 4. \u0424\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0430 (\u0411\u044b\u0441\u0442\u0440\u0430\u044f O(N log N) \u043d\u0430 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0438\u0437 'limit' \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432)\n    const resultPosts = fetchedPosts.sort((a, b) => {\n      const indexA = idToIndexMap.get(a._id.toString());\n      const indexB = idToIndexMap.get(b._id.toString());\n      return indexA - indexB; \n    });\n\n    \/\/ 5. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u043a\u0443\u0440\u0441\u043e\u0440\u0430\n    const nextCursor = hashtagDocs[hashtagDocs.length - 1].postCreatedAt.toISOString();\n\n    return res.status(200).json({ posts: resultPosts, nextCursor });\n  } catch (error) {\n    handleServerError(res, error);\n  }\n};\n<\/code><\/pre>\n \n\n<p><strong>\u0414\u043b\u044f \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0438 \u043f\u043e\u0441\u0442\u043e\u0432 \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u043c (\u043f\u043e \u0434\u0430\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f), \u0431\u044b\u043b\u0430 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0430 \u0434\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f:<\/strong><\/p>\n\n<p>\u041f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u043f\u043e\u0441\u0442\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u0445\u0435\u0448\u0442\u0435\u0433, \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 <code class=\"inline-code\">hashtags<\/code>, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043f\u043e\u043b\u0435 \u2014 <code class=\"inline-code\">postCreatedAt<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0434\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u043a\u0443 \u0438 \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044e \u043f\u043e\u0441\u0442\u043e\u0432 \u043f\u043e \u0434\u0430\u0442\u0435, \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 <code class=\"inline-code\">hashtags<\/code>, \u0431\u0435\u0437 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0439 \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 <code class=\"inline-code\">posts<\/code>. \u0412 <code class=\"inline-code\">getPostsByHashtag<\/code>, \u043f\u043e\u0438\u0441\u043a \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 <code class=\"inline-code\">hashtags<\/code> \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0431\u044b\u0441\u0442\u0440\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 <code class=\"inline-code\">find()<\/code>, \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f <strong>compound index<\/strong> \u2014 <code class=\"inline-code\">{ name: 1, postCreatedAt: -1 }<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 MongoDB, \u0431\u044b\u0441\u0442\u0440\u043e \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0443\u0436\u043d\u044b\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435.<\/p>\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">post.controller.js<\/h2>\n\n\n<pre class=\"wp-block-code lang-js line-numbers\"><code>export const createPost = async (req, res) => {\n  try {\n    const combiningTitleAndText = (req.body?.title + ' ' + req.body.text).split(\/[\\s\\n\\r]\/gmi).filter(v => v.startsWith('#'));\n    const hashtags = takeHashtags(combiningTitleAndText).map(tag => tag.replace(\/^#\/, '').toLowerCase());\n    if (hashtags.length > 30) {\n      return res.status(400).json({ message: 'Maximum 30 hashtags allowed' });\n    }\n    if (hashtags.some(tag => tag.length > 70)) {\n      return res.status(400).json({ message: 'Each hashtag must be 70 characters or less' });\n    }\n    const doc = new PostModel({\n      title: req.body?.title,\n      text: req.body.text,\n      mainImageUri: req.body.mainImageUri,\n      user: req.userId._id,\n    });\n    const mainImageUri = req.body.mainImageUri;\n    const text = req.body.text;\n    if (!(mainImageUri || (text.length >= 1))) {\n      return res.status(400).json({ message: 'Post should not be empty' });\n    }\n\n    \/\/ 1. \u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0441\u0442\u0430 (\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 ID \u0438 createdAt(postCreatedAt))\n    const post = await doc.save();\n\n    \/\/ 2. *** \u041b\u043e\u0433\u0438\u043a\u0430 \u0445\u044d\u0448\u0442\u0435\u0433\u043e\u0432 ***\n    const postId = post._id;\n    const postCreatedAt = post.createdAt;\n\n    if (hashtags.length > 0) {\n      const hashtagDocs = hashtags.map((tag) => ({\n        name: tag.toLowerCase(),\n        postId,\n        postCreatedAt, \/\/ \u0414\u0435\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043f\u043e\u043b\u0435\n      }));\n      await HashtagModel.bulkWrite(\n        hashtagDocs.map((doc) => ({\n          insertOne: { document: doc },\n        })),\n        { ordered: false } \n      );\n    }\n    \/\/ *** \u041a\u043e\u043d\u0435\u0446 \u043b\u043e\u0433\u0438\u043a\u0438 \u0445\u044d\u0448\u0442\u0435\u0433\u043e\u0432 ***\n\n    res.status(200).json(post);\n  } catch (error) {\n    handleServerError(res, error);\n  }\n};\n<\/code><\/pre>\n \n\n<p><strong>\u0414\u043b\u044f \u0438\u0437\u0431\u0435\u0436\u0430\u043d\u0438\u044f \u043b\u0438\u043c\u0438\u0442\u0430 \u0432 16 MB \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 - <code class=\"inline-code\">$in<\/code> \u0432 <code class=\"inline-code\">getPostsByHashtag<\/code>, \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u0442\u043e\u0432 \u0431\u044b\u043b \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d \u043d\u0430 \u0434\u0432\u0430 \u044d\u0442\u0430\u043f\u0430:<\/strong><\/p>\n\n<p><strong>1. \u0411\u044b\u0441\u0442\u0440\u044b\u0439 Index Scan.<\/strong><\/p> \n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043a \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 <code class=\"inline-code\">hashtags<\/code>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u043f\u043e\u0441\u0442\u043e\u0432, \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 <code class=\"inline-code\">.limit(N)<\/code> (\u043e\u0431\u044b\u0447\u043d\u043e N = 10-20). \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 <code class=\"inline-code\">postIds<\/code> \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0430, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u043f\u043e\u0441\u0442\u044b.<\/p>\n\n<p><strong>2. \u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0441 <code class=\"inline-code\">$in<\/code>.<\/strong><\/p>\n<p>\u041c\u0430\u0441\u0441\u0438\u0432 <code class=\"inline-code\">postIds<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u043f\u043e\u043b\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 <code class=\"inline-code\">posts<\/code>.\n\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043c\u0430\u043b\u043e\u043c\u0443 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u0432 \u0432 <code class=\"inline-code\">postIds<\/code>, \u0437\u0430\u043f\u0440\u043e\u0441 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e \u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0440\u0438\u0441\u043a \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u0438\u044f BSON-\u043b\u0438\u043c\u0438\u0442\u0430 \u0432 16 MB.<\/p>\n\n<h2 id=\"paragraph_6\">6. \u041f\u043b\u0430\u043d\u044b \u043f\u043e \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c\u0443 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/h2>\n\n<p>\u0412 \u0432\u0435\u0440\u0441\u0438\u0438 CRYSTAL v2.0 \u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u043b\u0430\u0439\u043a\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044e, \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0443\u044e \u0434\u043b\u044f \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0440\u0435\u0430\u043a\u0446\u0438\u0439. \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, Mongoose \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043c\u0435\u043d\u0451\u043d \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u043c MongoDB, \u0447\u0442\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442 \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u0440\u043e\u0441\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 CRUD-\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u0441\u043d\u0438\u0437\u0438\u0442 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 \u043f\u0440\u0438 \u043c\u0430\u0441\u0441\u043e\u0432\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445 \u0438 \u043f\u043e\u0432\u044b\u0441\u0438\u0442 \u043e\u0431\u0449\u0443\u044e \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n\n<div class=\"browserstack_testing__announcement___wrap\">\n         <div class=\"browserstack_testing__announcement\">\n            <div class=\"browserstack_testing__announcement___top\">\n               <p>CRYSTAL \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0432 <\/p>\n            <\/div>\n            <div class=\"browserstack_testing__announcement___bottom\">\n               <svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" xmlns:xlink=\"http:\/\/www.w3.org\/1999\/xlink\" viewBox=\"0 -1.5 31 33\">\n               <g fill=\"none\" fill-rule=\"evenodd\"> <\/g>\n               <g>\n                  <path d=\"m31.0344828 15.5172414c0 8.5701882-6.9470532 15.5172414-15.5172414 15.5172414-8.56989423 0-15.5172414-6.9470532-15.5172414-15.5172414 0-8.56989423 6.94734717-15.5172414 15.5172414-15.5172414 8.5701882 0 15.5172414 6.94734717 15.5172414 15.5172414\" fill=\"#ecb360\"><\/path>\n                  <path d=\"m26.8965517 13.9655172c0 7.7128847-6.0213369 13.9655173-13.4482758 13.9655173-7.42722227 0-13.4482759-6.2526326-13.4482759-13.9655173 0-7.71288459 6.02105363-13.9655172 13.4482759-13.9655172 7.4269389 0 13.4482758 6.25263261 13.4482758 13.9655172\" fill=\"#d76835\"><\/path>\n                  <path d=\"m27.9310345 12.4136422c0 6.8560652-5.3263006 12.413944-11.8969855 12.413944-6.5698174 0-11.89611797-5.5578788-11.89611797-12.413944 0-6.85576335 5.32630057-12.4136422 11.89611797-12.4136422 6.5706849 0 11.8969855 5.55787885 11.8969855 12.4136422\" fill=\"#d33a41\"><\/path>\n                  <path d=\"m26.8965517 13.4484262c0 6.2843054-4.8632703 11.37916-10.8622124 11.37916-5.9989422 0-10.86192551-5.0948546-10.86192551-11.37916 0-6.28490677 4.86298331-11.37946068 10.86192551-11.37946068 5.9989421 0 10.8622124 5.09455391 10.8622124 11.37946068\" fill=\"#b6cb46\"><\/path>\n                  <path d=\"m25.862069 14.4826111c0 5.7133106-4.6316645 10.3449751-10.3449751 10.3449751-5.71301565 0-10.34468011-4.6316645-10.34468011-10.3449751 0-5.71331065 4.63166446-10.34468007 10.34468011-10.34468007 5.7133106 0 10.3449751 4.63136942 10.3449751 10.34468007\" fill=\"#66ad4a\"><\/path>\n                  <path d=\"m21.7241379 12.4137931c0 4.5706247-3.7052373 8.2758621-8.275862 8.2758621-4.57090515 0-8.27586211-3.7052374-8.27586211-8.2758621 0-4.57062469 3.70495696-8.27586207 8.27586211-8.27586207 4.5706247 0 8.275862 3.70523738 8.275862 8.27586207\" fill=\"#aed7dc\"><\/path>\n                  <path d=\"m22.7586207 11.3793103c0 3.9991764-3.2419755 7.2413794-7.2415259 7.2413794-3.9995505 0-7.24123273-3.242203-7.24123273-7.2413794 0-3.99946945 3.24168223-7.24137927 7.24123273-7.24137927 3.9995504 0 7.2415259 3.24190982 7.2415259 7.24137927\" fill=\"#5bb1cf\"><\/path>\n                  <path d=\"m22.7586207 11.8963967c0 3.7136422-2.7788402 6.724293-6.2068966 6.724293s-6.2068965-3.0106508-6.2068965-6.724293c0-3.71333217 2.7788401-6.72398291 6.2068965-6.72398291s6.2068966 3.01065074 6.2068966 6.72398291\" fill=\"#25a8c3\"><\/path>\n                  <path d=\"m20.6896552 12.9308813c0 3.1423524-2.315869 5.6898084-5.1725531 5.6898084-2.8564055 0-5.1722745-2.547456-5.1722745-5.6898084 0-3.14235241 2.315869-5.68950199 5.1722745-5.68950199 2.8566841 0 5.1725531 2.54714958 5.1725531 5.68950199\"><\/path>\n                  <path d=\"m15.5171021 18.6206897c-2.8564055 0-5.1722745-2.547456-5.1722745-5.6898084 0-3.14235241 2.315869-5.68950199 5.1722745-5.68950199 2.8566841 0 5.1725531 2.54714958 5.1725531 5.68950199 0 3.1423524-2.315869 5.6898084-5.1725531 5.6898084z\" fill=\"#1b1a18\"><\/path>\n                  <path d=\"m18.3395432 11.2904163c-.4920811.8231975-1.4595626 1.299291-2.16129 1.062668-.7017274-.2363383-.8715674-1.0956984-.3798654-1.9191807.4920811-.82348231 1.4595626-1.29929107 2.16129-1.06295279s.8715674 1.09569839.3798654 1.91946549\" fill=\"#fffffe\"><\/path>\n               <\/g>\n               <\/svg>\n               <p>BrowserStack<\/p>\n            <\/div>\n            <a href=\"https:\/\/www.browserstack.com\/\" target=\"blank\" rel=\"noopener\" aria-label=\"\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 browserstack\">\n            <\/a>\n         <\/div>\n      <\/div>","protected":false},"excerpt":{"rendered":"\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435: 1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 2. \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 npm \u043f\u0430\u043a\u0435\u0442\u043e\u0432 3. \u0412\u0438\u0434\u0435\u043e \u0441 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0438 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f CRYSTAL v2.0 4. \u0410\u043d\u0430\u043b\u0438\u0437 \u0441\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f 5. \u041d\u043e\u0432\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432 6. \u041f\u043b\u0430\u043d\u044b \u043f\u043e \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u043c\u0443 \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 1. \u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0421\u0438\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u043d\u0443\u0436\u043d\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0441 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430\u043c\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439, \u043f\u043e\u0441\u0442\u043e\u0432, \u043b\u0430\u0439\u043a\u043e\u0432, \u0445\u0435\u0448\u0442\u0435\u0433\u043e\u0432 \u0438 \u0442.\u0434. \u0426\u0435\u043b\u044c [&hellip;]","protected":false},"author":1,"featured_media":3641,"comment_status":"closed","ping_status":"closed","sticky":true,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20,42,4,47,48,24,25,60,44,46,45,59,50,52,51,49,65,55],"tags":[],"class_list":["post-3647","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-crystal","category-crystal-v2-0","category-js","category-mongochecker","category-mongocollector","category-mongodb","category-node-js","category-nosql","category-npm","category-supermaker","category-turbomaker","category-bazy-dannyh","category-50","category-52","category-51","category-49","category-yazyki-programmirovaniya","category-dnevnik-razrabotchika-crystal"],"_links":{"self":[{"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/posts\/3647","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/comments?post=3647"}],"version-history":[{"count":15,"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/posts\/3647\/revisions"}],"predecessor-version":[{"id":4340,"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/posts\/3647\/revisions\/4340"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/media\/3641"}],"wp:attachment":[{"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/media?parent=3647"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/categories?post=3647"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/shedov.top\/ru\/wp-json\/wp\/v2\/tags?post=3647"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}