У меня есть 2 коллекции в MongoDB, которые относятся друг к другу. 2 коллекции: - Профили и ссылки на посты OBjectId
- Посты со ссылкой на Профили username: {type: Connect.Schema.Types.String}
Моя проблема в том, что в NodeJS API мне нужно выполнить POST для создания нового отправьте URL-адрес примерно так: POST /api/v1/posts/:username
, поскольку я публикую для указанного c имя пользователя. POST должен создать новый пост с таким телом, как:
{
"text": "something"
}
Тогда мне нужно будет увидеть в ответе, если я GET
the :username
наберу
{
"username": ":username"
"text": "something"
}
Имя пользователя должно совпадать с именем пользователя в параметрах URL. Поэтому я могу ПОЛУЧИТЬ все сообщения для одного имени пользователя.
Я сделал это, но на самом деле это неправильно, так как я не должен передавать тело имени пользователя, так как оно упоминается в профилях через этот параметр :username
.
// Create a new one for the username
async createNew(req, res) {
try {
// Check for an empty body
if (Object.keys(req.body).length === 0) {
throw new ErrorHandlers.ErrorHandler(500, "Nothing to create");
}
// Req body
const newPost = req.body;
// Creating the new post and updating the profile ref
const addNewPost = await Post.create(newPost);
addNewPost.username = req.body.username;
const updateProfile = await Profile.findOneAndUpdate(
{ username: res.username.username },
{ $push: { posts: addNewPost._id } },
{ new: true }
);
// Error Check
if (!addNewPost && !updateProfile) {
throw new ErrorHandlers.ErrorHandler(
500,
"Not possible create a new post"
);
}
// Response
res.status(200).json({
username: res.username.username,
newPost: newPost
});
} catch (err) {
res.status(500).json(err);
}
}
Мои модели:
// Here defining profile model
// Embedded we have the Experience as []
const { Connect } = require("../db");
const { isEmail } = require("validator");
const postSchema = {
type: Connect.Schema.Types.ObjectId,
ref: "Post"
};
const experienceSchema = {
role: {
type: String,
required: true
},
company: {
type: String,
required: true
},
startDate: {
type: Date,
required: true
},
endDate: {
type: Date,
required: false
},
description: {
type: String,
required: false
},
area: {
type: String,
required: true
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
username: {
type: String,
required: false
},
image: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
}
};
const profileSchema = {
firstname: {
type: String,
required: true
},
surname: {
type: String,
required: true
},
email: {
type: String,
trim: true,
lowercase: true,
unique: true,
required: [true, "Email is required"],
validate: {
validator: string => isEmail(string),
message: "Provided email is invalid"
}
},
bio: {
type: String,
required: true
},
title: {
type: String,
required: true
},
area: {
type: String,
required: true
},
imageUrl: {
type: String,
required: false,
default: "https://via.placeholder.com/150"
},
username: {
type: String,
required: true,
unique: true
},
experience: [experienceSchema],
posts: [postSchema],
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
}
};
const collectionName = "profile";
const profileSchemaModel = Connect.Schema(profileSchema);
const Profile = Connect.model(collectionName, profileSchemaModel);
module.exports = Profile;
const { Connect } = require("../db");
const reactionSchema = {
likedBy: {
type: String,
unique: true,
sparse: true
}
};
const postSchema = {
text: {
type: String,
required: true,
unique: true,
sparse: false
},
username: {
type: Connect.Schema.Types.String,
ref: "Profile",
required: true
},
image: {
type: String,
default: "https://via.placeholder.com/150",
required: false
},
createdAt: {
type: Date,
default: Date.now,
required: false
},
updatedAt: {
type: Date,
default: Date.now,
required: false
},
reactions: [reactionSchema],
comments: {
type: Connect.Schema.Types.ObjectId,
ref: "Comment",
required: false
}
};
const collectionName = "post";
const postSchemaModel = Connect.Schema(postSchema);
const Post = Connect.model(collectionName, postSchemaModel);
module.exports = Post;
Я хотел бы найти решение для POST одного сообщения для определенного c имени пользователя, указанного в профиле, а затем ПОЛУЧИТЬ все сообщения для одного имени пользователя, как я попробовал ниже без успеха:
async getAllFromProfile(req, res) {
try {
const postsFromUsername = await Profile.aggregate([
{
$match: {
username: res.username.username
}
},
{
$lookup: {
from: "posts ",
localField: "_id",
foreignField: "username",
as: "posts"
}
},
{
$project: {
username: 1,
posts: 1,
postsCount: {
$size: "$posts"
},
_id: 0
}
}
]);
if (postsFromUsername.length > 0) {
res.json({ postsFromUsername: postsFromUsername });
} else {
throw new ErrorHandlers.ErrorHandler(500, "No data");
}
} catch (err) {
res.status(500).json(err);
}
},