I am developing a questionnaire in MERN stack - one question per page (e.g. "Specify name" on one page, click next question, "Specify company name" on another page etc.), about 40 pages.
When clicking "Next" the app saves user's answer in the localStorage, retrieves from localStorage and sends an axios.post to express server, which finds a MongoDB document by uuid and updates it with a new answer.
The problem is that not all answers are saved in the MongoDB. After some questions the answers stop saving to MongoDB. Only when I restart the express server and try again to answer the question, then it saves it to MongoDB.
I have no idea what's wrong. Any suggestions are welcome
Here is a code example:
//React:
import { useState } from "react";
import axios from "axios";
import { useHistory } from "react-router-dom";
import NextQuestion from "./NextQuestion";
export default function Question1() {
const history = useHistory();
const [input, setInput] = useState("");
function handleChange(e) {
setInput(e.target.value);
}
function handleSubmit(e) {
e.preventDefault();
localStorage.setItem("name", input);
const data = {
uuid: localStorage.getItem("uuid"),
name: localStorage.getItem("name"),
};
axios.post("/answers", data);
history.push("/next-question");
}
return (
<BrowserRouter>
<Route path="/question-1">
<form>
<input id="name" type="text" value={value} onChange={handleChange} />
<label for="#name">Please specify your name</label>
<button onClick={handleSubmit}>NEXT QUESTION</button>
</form>
</Route>
<Switch>
<Route path="/next-question">
<NextQuestion />
</Route>
</Switch>
</BrowserRouter>
);
}
//Express server:
require("dotenv").config();
const express = require("express");
const app = express();
const cors = require("cors");
const mongoose = require("mongoose");
app.use(express.json());
app.use(cors());
mongoose.connect(process.env.MONGO_URI);
const answerSchema = {
uuid: String,
name: String,
company: String,
title: String,
email: String,
phone: String,
};
const Answer = mongoose.model("Answer", answerSchema);
app.post("/answers", (req, res) => {
if (req.body.uuid) {
Answer.updateOne(
{ uuid: req.body.uuid },
{
name: req.body.name,
company: req.body.company,
title: req.body.title,
email: req.body.email,
phone: req.body.phone,
},
{
upsert: true,
}
)
.then((item) => console.log(item))
.catch((err) => res.status(400).json("Error " err));
} else {
const newAnswer = new Answer({
uuid: req.body.uuid,
name: req.body.name,
company: req.body.company,
title: req.body.title,
email: req.body.email,
phone: req.body.phone,
});
newAnswer
.save()
.then((item) => console.log(item))
.catch((err) => res.status(400).json("Error " err));
}
});
app.listen(3001, function () {
console.log("Express is running");
});
CodePudding user response:
Original answer: How do I update/upsert a document in Mongoose?
Please make sure to give credit to the original respondent
Mongoose now supports this natively with findOneAndUpdate (calls MongoDB findAndModify).
The { upsert: true }
option creates the object if it doesn't exist. defaults to false.
var query = {'username': req.user.username};
req.newData.username = req.user.username;
MyModel.findOneAndUpdate(query, req.newData, {upsert: true}, function(err, doc) {
if (err) return res.send(500, {error: err});
return res.send('Succesfully saved.');
});
In older versions Mongoose does not support these hooks with this method:
- defaults
- setters
- validators
- middleware