I can't figure out how to add data to a mongoose sub-document when I create a new schema from the client side. The only data that gets sent over to the data base is the data that is not nested inside another schema/array.
I'm using MongoDB with Mongoose for my database and NextJS as my both my front and back end.
I've haven't been able to find a way to get this working yet. Any help would be appreciated.
This is the back end route:
export default async (req, res) => {
const { method } = req;
switch (method) {
case "POST":
try {
const workout = req.body;
const newWorkout = new Workout({ ...workout });
await newWorkout.save();
res.status(201).json({ success: true, data: newWorkout });
} catch (error) {
res.status(400).json({ success: false });
}
break;
This is the mongoose schema:
import mongoose from "mongoose";
const reqString = {
type: String,
required: true,
};
const WodSchema = new mongoose.Schema({
exerciseName: reqString,
repCount: reqString,
});
const exerciseSchema = new mongoose.Schema({
workoutName: String,
workoutContent: [WodSchema],
});
const WorkoutSchema = new mongoose.Schema({
name: { type: String },
workout: [exerciseSchema],
// timestamps: true,
});
module.exports =
mongoose.models.Workout || mongoose.model("Workout", WorkoutSchema);
This is the front end post request (only name gets sent to db):
const [name, setName] = useState("");
const [workoutName, setWorkoutName] = useState("");
const [exerciseName, setExerciseName] = useState("");
const editProgram = async () => {
try {
const res = await fetch(`http://localhost:3000/api/workouts/`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ name, workoutName, exerciseName }),
});
} catch (error) {
console.log(error);
}
};
Solution:
case "POST":
try {
const workout = req.body;
const newWorkout = new Workout({
name: workout.name,
workout: {
workoutName: workout.workoutName,
workoutContent: {
exerciseName: workout.exerciseName,
repCount: workout.repCount,
},
},
});
await newWorkout.save();
res.status(201).json({ success: true, data: newWorkout });
} catch (error) {
res.status(400).json({ success: false });
}
Related
I created an API for following and followers user for Social Media Application, while request from postman getting empty object: {} But it seems to me to be correct.
Model:
const mongoose = require("mongoose");
const UserSchema = mongoose.Schema({
username: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
firstname: {
type: String,
required: true,
},
lastname: {
type: String,
required: true,
},
isAdmin: {
type: Boolean,
default: false,
},
profilePicture: String,
coverPicture: String,
about: String,
livesin: String,
workAt: String,
relationship: String,
followers: [],
following: []
},{
timestamps:true
}
);
const UserModel = mongoose.model("Users", UserSchema);
module.exports = UserModel;
UserControler:
const UserModel = require("../Models/Usermodel");
const bcrypt = require("bcryptjs");
const followUser = async (req, res) => {
const id = req.params.id.trim();
const { currentUserId } = req.body;
if (currentUserId === id) {
res.status(403).send("Action forbiden");
} else {
try {
const followUser = await UserModel.findById(id);
const followingUser = await UserModel.findById(currentUserId);
if (!followUser.followers.includes(currentUserId)) {
await followUser.updateOne({ $push: { followers: currentUserId } });
await followingUser.updateOne({ $push: { following: id } });
res.status(200).send({message:"User Followed"});
} else {
res.status(403).send("User alredy followed by you!");
}
} catch (error) {
res.status(500).send(error);
}
}
};
module.exports = { getUser, updateUser, userDelete, followUser };
UserRoute:
const express = require("express");
const {getUser,updateUser, userDelete, followUser} = require("../Controller/userControler");
const router = express.Router()
router.get("/:id",getUser)
router.put("/:id",updateUser)
router.delete("/:id", userDelete)
router.put("/:id/follow", followUser)
module.exports=router;
index.js:
app.use("/user",UserRoute)
Here is the complete details regarding the error, let me know what happens in the code, thank you.
i assume that you have all the other functions other than followUser in your controller.js
The thing is that you must first specify the field name on the basis of which you want to update the document.
Here is what you need to do;
const UserModel = require("../Models/Usermodel");
const bcrypt = require("bcryptjs");
const mongoose = require("mongoose");//updated line
const followUser = async (req, res) => {
const id = req.params.id.trim();
const { currentUserId } = req.body;
if (currentUserId === id) {
res.status(403).send("Action forbiden");
} else {
try {
const followUser = await UserModel.findById({_id: mongoose.Types.ObjectId(id)});
const followingUser = await UserModel.findById({_id: mongoose.Types.ObjectId(currentUserId)});
if (!followUser.followers.includes(currentUserId)) {
await followUser.updateOne({_id: mongoose.Types.ObjectId(*id of the user you want to update*)},{ $push: { followers: currentUserId } });
await followingUser.updateOne({_id: mongoose.Types.ObjectId(*id of the user you want to update*)}{ $push: { following: id } });
res.status(200).send({message:"User Followed"});
} else {
res.status(403).send("User alredy followed by you!");
}
} catch (error) {
res.status(500).send(error);
}
}
};
module.exports = { getUser, updateUser, userDelete, followUser };
And while hitting the api pls make sure that your route should be
localhost:port-number/user/12345789/follow
and also make sure that the API type in postman must be same as in the backend e.g; PUT
please try findByIdAndUpdate query insted of using updateOne
hi guys i have an error when i try to send array of string with Mongoose Schema
//Mongoose Schema
const mongoose = require('mongoose');
const { Schema } = mongoose;
const NotesSchema = new Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
title: {
type: String,
required: true
},
description: {
type: String,
required: true,
},
tag: {
type: String,
default: "General"
},
date: {
type: Date,
default: Date.now
},
});
module.exports = mongoose.model('notes', NotesSchema);
AddNote.js
import React, { useContext, useState } from 'react';
import noteContext from '../context/notes/noteContext';
const AddNote = () => {
const context = useContext(noteContext);
const {addNote } = context;
const [note, setNote] = useState({title: "", description: "", tag: ""})
const handleClick = (e)=>{
e.preventDefault();
addNote(note.title, note.description, note.tag);
setNote({title: "", description: "", tag: ""});
}
const onChange = (e)=>{
setNote({...note, [e.target.name]: [e.target.value]})
}
NoteState.js
const addNote = async (title, description, tag) => {
//API Call
const response = await fetch(`${host}/api/notes/addnote`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'auth-token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoiNjM3MTRhYmFlZjgzNDIyOWY5YjE3YzllIn0sImlhdCI6MTY2ODM2OTE0Mn0.uYT7hxbKNRzsuJjMNpuLozIDcAFnvLFQMxykOnzHQ-s'
},
body: JSON.stringify({title, description, tag})
});
const json = await response.json();
console.log(json);
console.log("Adding a new node");
const note = {
"_id": "63754143ce60e68405f291e3",
"user": "63714abaef834229f9b17c9e",
"title": title,
"description": description,
"tag": tag,
"date": "2022-11-16T19:35:47.035Z",
"__v": 0
};
setNotes(notes.concat(note))
}
when i try to addNote i got an error for notes validation failed: title: Cast to string failed for value "[ 'sddgfgg' ]" (type Array) at path "title", description: Cast to string failed for value "[ 'dgfgdgd' ]" (type Array) at path "description", tag: Cast to string failed for value "[ 'fdgfg' ]" (type Array) at path "tag"
notes.js
const express = require('express');
const router = express.Router();
const Note = require('../models/Note');
const fetchuser = require('../middleware/fetchuser');
const { body, validationResult } = require('express-validator');
// Route 1: get all the nots using: GET "/api/notes/fetchallnotes" Login required
router.get('/fetchallnotes', fetchuser, async (req, res) => {
try {
const notes = await Note.find({ user: req.user.id });
res.json(notes)
} catch (error) {
console.error(error.message)
res.status(500).send("Internal server error occured");
}
})
// Route 2: Add a new notes using: POST "/api/notes/addnote" Login required
router.post('/addnote', fetchuser, [
body('title', 'Enter a avalid tilte').isLength({ min: 3 }),
body('description', 'Description must be atleast 5 character').isLength({ min: 5 }),], async (req, res) => {
try {
const { title, description, tag } = req.body;
// if there are errors , return bad request and the errors
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const note = new Note({
title, description, tag, user: req.user.id
})
const saveNotes = await note.save()
res.json(saveNotes)
} catch (error) {
console.error(error.message)
res.status(500).send("Internal server error occurred");
}
})
As the title suggests my fetched data isn't storing in the state. I think it is something to do with the loading sequence but I can't be sure because I am still new, especially when it comes to axios fetching. Using the useEffect to check the state I see that formData.organizer starts empty, get the userId string, then gets emptied again.
usersController
exports.myAccount = async (req, res) => {
try {
const user = await User.find({ email: req.email }, { _id: 1 });
res.status(201).json({
status: 'success',
user,
});
} catch (err) {
res.status(404).json({
status: 'fail',
message: err,
});
}
};
Create Event Container
const [formData, setFormData] = useState({
...
organizer: '',
})
useEffect(() => {
getMyAccount();
}, []);
const getMyAccount = async () => {
let data;
try {
const res = await axiosPrivate.get('/api/users/myaccount');
data = await res.data.user[0]._id;
setFormData({
...formData,
organizer: data,
});
} catch (err) {
console.log(err);
}
};
useEffect(() => {
console.log(`organizer in formData:${formData.organizer}`);
}, [formData.organizer]);
import axios from 'axios';
const BASE_URL = 'http://localhost:5000';
export default axios.create({
baseURL: BASE_URL,
});
export const axiosPrivate = axios.create({
baseURL: BASE_URL,
headers: {
'Content-Type': 'application/json',
},
withCredentials: true,
});
Thanks in advance for any help!
I've been struggling with this issue for a day now and can't seem to figure out a way to resolve it. This is the code I'm running
Client side:
const nameInput = document.querySelector("#nameInput");
const urlInput = document.querySelector("#urlInput");
const rowAlert = document.querySelector(".alertAppend");
const divAlert = document.createElement("div");
const nameUpdate = async (e) => {
e.preventDefault();
fetch("/auth/updateName", {
method: 'POST',
headers: {
'Content-Type' : 'application/json'
},
body: JSON.stringify({
name: nameInput,
url: urlInput,
})
})
.then(function (data) {
console.log('Request success: ', data);
})
.catch(function (error) {
console.log('Request failure: ', error);
});
};
submitName.addEventListener("click", nameUpdate);
API:
router.get("/updateName", auth, async (req, res) =>{
try {
const { name, url } = req.body;
const ime = name;
const uid = req.session.passport.user;
db.User.find({ where: { id: uid } })
.on('success', function (user) {
if (user) {
user.update({
name: ime,
webhook: url
})
.success(function () {})
}
})
res.json({ message: url});
} catch (err) {
if (err) res.status(500).json({ message: "Internal Error"})
}
});
For some reason it just runs the select query and never proceeds to update the user.
Chrome console output
Debug console output
Sequelize model in case it helps:
module.exports = function (sequelize, DataTypes) {
var User = sequelize.define("User", {
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true
}
},
password: {
type: DataTypes.STRING,
allowNull: false
},
name: {
type: DataTypes.STRING
}
})
return User;
}
The issue was in the API, it's supposed to be router.post
router.post("/updateName", auth, async (req, res) =>{
const { ime, url } = req.body;
const uid = req.session.passport.user;
console.log(ime);
db.User.findOne({where: {id: uid}})
.then(record => {
let values = {
name: ime,
webhook: url
}
record.update(values).then( updatedRecord => {
console.log(`updated record ${JSON.stringify(updatedRecord,null,2)}`)
res.status(200).json({ message: "success"});
})
}
})
.catch((error) => {
// do seomthing with the error
throw new Error(error)
})
});
You can try the following code
await db.User.update({
name: ime,
webhook: url
}, { where: { id: uid } });
When defining your model I don't see the webhook field
I want to create a complex nested document which can store values like this
category: {
"fish": ["Sardines", "Goldfish"],
"dogs": ["German Shepherd", "Dobberman"]
}
Here's what I tried
export const CategorySchema = new mongoose.Schema(
{
category: {
type: Map,
of: [String],
},
},
{ timestamps: true }
);
I passed data like this (from console)
this is how the passed data looks like
Nothing is being created in the database. Also no error.
export default async (req, res) => {
const { method } = req;
switch (method) {
case "GET":
try {
const categories = await Category.find({});
res.json({ success: true, data: categories });
} catch (error) {
res.json({ success: false });
}
break;
case "POST":
try {
let data = req.body;
data = JSON.parse(data);
const category = new Category(data);
const doc = await category.save();
console.log("Doc from Categories API", doc);
res.json({ success: true, data: doc });
} catch (error) {
res.json({ success: false });
}
break;
default:
res.status(400).json({ success: false });
break;
}
};
Can anyone advise me, please?