Home > other >  MongoDB: when deleting an old collection and inserting a new collection, sometimes the new collectio
MongoDB: when deleting an old collection and inserting a new collection, sometimes the new collectio

Time:12-05

There is a form with input text fields, used to define a list of flavors. Submitting the form should delete the old flavor collection and replace it with the new flavor collection.

Example of flavors collection: [{name: vanilla}, {name: chocolate}].

The database is MongoDB, The server side uses Node.JS Express Mongoose, The client side uses React.

Sometimes the program works properly, but sometimes after submitting the form several times, the old collection is deleted but the new collection is not saved without any error appearing, and sometimes an error appears that the id is duplicated key.

In some of the answers I found on stackoverflow I read that it should be defined "{ ordered: false }". I tried, as shown in the attached code, but that didn't solve the problem either.

server side:

flavorsModel.js

import "dotenv/config.js";

import { Schema, model } from "mongoose";

const flavorsSchema = new Schema({
    name: {
        type: String,
        require: true,
    },
});

export default model("", flavorsSchema, process.env.MONGODB_COLLECTION_NAME);

flavorsController.js

import flavorsModel from "../models/flavorsModel.js";

export async function loadFlavors(_, res) {
    const flavors = await flavorsModel.find().catch((err) => console.log(err));
    res.send(flavors);
    console.log("flavors loaded", flavors);
}

export async function deleteFlavors() {
    await flavorsModel.deleteMany().catch((err) => console.log(err));
    console.log("flavors deleted");
}

export async function saveFlavors(req, _) {
    const flavors = await flavorsModel
        .insertMany(req.body, { ordered: false })
        .catch((err) => console.log(err));
    console.log("flavors saved", flavors);
}

flavorsRoute.js

import { Router } from "express";
import { loadFlavors, deleteFlavors, saveFlavors} from "../controllers/flavorsController.js";

const router = Router();
router.get("/loadFlavors", loadFlavors);
router.delete("/deleteFlavors", deleteFlavors);
router.post("/saveFlavors", saveFlavors);

export default router;

server.js

import cors from "cors";
import "dotenv/config.js";
import express from "express";
import mongoose from "mongoose";
import flavorsRoute from "./routes/flavorsRoute.js";

const app = express();
const port = process.env.port || 5000;

mongoose
    .connect(process.env.MONGODB_URL)
    .then(() => console.log("MongoDB connected"))
    .catch((err) => console.log(err));

app.use(cors());
app.use("/flavors", flavorsRoute);

app.listen(port, () => {
console.log(`Server on port http://localhost:${port}`);
});

client side:

import axios from "axios";

const baseUrl = "http://localhost:5000/flavors";

const loadFlavors = (setFlavors) => {
    axios.get(`${baseUrl}/loadFlavors`).then(({ data }) => {
        console.log("data", data);
        setFlavors(data);
    });
};

const saveFlavors = (flavors) => {
    axios
        .all([
            axios.delete(`${baseUrl}/deleteFlavors`, {}),
            axios.post(`${baseUrl}/saveFlavors`, flavors),
        ])
        .catch((err) => console.log(err));
};
export { loadFlavors, saveFlavors };

CodePudding user response:

By using axios.all() you are running the deletion request and the save request in parallel. If you get lucky, the save will happen after the delete, and everything will be fine. If you get unlucky, the save will happen before or during the delete, and cause behavior like you describe.

To run them in order would be something like:

const saveFlavors = async (flavors) => {
  await axios.delete(`${baseUrl}/deleteFlavors`, {}).catch((err) => console.log(err));
  await axios.post(`${baseUrl}/saveFlavors`, flavors).catch((err) => console.log(err));
};

You will also need to update your backend to send responses from those routes, or the frontend will hang while waiting for a response that isn't coming.

  • Related