MongoDB: No write concern mode named 'majority a' found in replica set configuration - mongodb

I am working through a traversy media tutorial and I've come across an error (in the title) that I'm not familiar with. I've been trying to learn about this but I'm still stumped as to why its appearing and where its coming from. Furthermore, I havent found any direct matches for this issue.
Here is the code in question, the catch at the bottom is returning the error.message.
edit: its also worth noting that I am able to successfuly add users to my database. So, it runs through the try block but also the catch ... so thats a big confusing. The only response I am getting on postman is the server error 500 message from the catch block.
const express = require('express');
const router = express.Router();
const gravatar = require('gravatar');
const bcrypt = require('bcryptjs');
const { check, validationResult } = require('express-validator');
const User = require('../../models/User');
// #route GET api/users
// #desc Test route
// #access Public
router.post(
'/',
[
check('name', 'Name is required').not().isEmpty(),
check('email', 'Please include a valid email').isEmail(),
check(
'password',
'Please enter a password with 6 or more characters'
).isLength({ min: 6 }),
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
const { name, email, password } = req.body;
try {
let user = await User.findOne({ email });
// see if user exists
if (user) {
return res.status(400).json({
errors: [{ msg: 'User already exists' }],
});
}
// get users gravatar
const avatar = gravatar.url(email, {
s: '200',
r: 'pg',
d: 'mm',
});
user = new User({
name,
email,
avatar,
password,
});
// encrypt password
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
// return jsonwebtoken
return res.send('User registered');
} catch (error) {
console.log(error.message);
res.status(500).send('Server error');
}
}
);
module.exports = router;
The User schema
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
},
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
avatar: {
type: String,
},
date: {
type: Date,
default: Date.now,
},
});
const User = mongoose.model('user', UserSchema);
module.exports = User;
connection configuration:
const mongoose = require('mongoose');
const config = require('config');
const db = config.get('mongoURI');
const connectDB = async () => {
try {
await mongoose.connect(db, {
useUnifiedTopology: true,
useNewUrlParser: true,
useCreateIndex: true,
});
console.log('Connected to MongoDB');
} catch (err) {
console.error(err.message);
process.exit(1);
}
};
module.exports = connectDB;

Related

How to get signed in users data?

I have a MERN mobile app thats using passportjs to authenticate and login users (with mongodb database and axios), however, when i eventually get to the the screen to enter in data (a "log"), i cant associate that data/log with the signed in user. How can i grab the user id several screens later after they have already signed in to associate it with the entry? My mongodb database has a number of users, so i only want a specific user's data (eg calories), ie the one that is currently logged in:
// Mongoose schemas
// log.model.js
const Schema = mongoose.Schema;
const logSchema = new Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
calories: {
type: Number,
required: true,
},
},
{
timestamps: true,
}
);
const Log = mongoose.model("Log", logSchema);
// user.model.js
const userSchema = new Schema(
{
_id: Schema.Types.ObjectId, // user id
email: {
type: String,
required: true,
unique: true,
trim: true,
},
password: {
type: String,
required: true,
trim: true,
minlength: 6,
},
},
{
timestamps: true,
}
);
const User = mongoose.model("User", userSchema);
They are first prompted to signin in the app, where they will then navigate to Home. Not all features are added in yet, just in development stage now:
// ./frontend/screens/signin.js
function onLoginPress() {
axios({
method: "POST",
data: {
email: email,
password: password,
},
withCredentials: true,
url: 'http:localhost:5000/users/signin',
})
.then((res) => console.log(res.data))
.catch((error) =>
console.log("ERROR: Promise rejected (sign in): " + error)
);
navigation.navigate("Home");
}
// ./backend/routes/users.js
router.route("/signin").post((req, res, next) => {
passport.authenticate("local", (error, user, info) => {
if (error) {
res.json({
status: "FAILED",
message: error,
});
}
if (!user) {
res.json({
status: "FAILED",
message: "No user exists",
});
} else {
req.logIn(user, (error) => {
if (error) console.log("ERROR: " + error);
res.json({
status: "SUCCESS",
message: "Successfully authenticated",
});
console.log(req.user);
});
}
})(req, res, next);
});
After they sign in, and they wish to enter in calories, i attempt to associate that log (and any future logs they might add) with the signed in user when they hit a button:
// ./frontend/screens/log.js
const [calories, setCalories] = React.useState("");
function onSaveLog() {
axios({
method: "post",
url: "http://localhost:5000/log/add",
data: {
calories: calories,
// CANT GET USER ID HERE?
},
})
.then((res) => {
console.log(res.data);
})
.catch(function () {
console.log("LOG ERROR: promise rejected");
});
}
// ./backend/routes/log.js
router.route("/add").post((req, res) => {
const calories = Number(req.body.calories);
// const user = req.body.user; // CANT GET THE USER ID HERE
const newLog = new Log({
calories,
// user,
});
// saves Log data to mongodb
newLog
.save()
.then(() => res.json("Log added"))
.catch((err) => res.status(400).json("Error: " + err));
});
so, what you doubt is, correct me if I'm wrong is that you want an ID that can be accessed somewhere later in the app to retrieve the users' data.
There are many ways to achieve that,
after you get the id, you can pass it as Navparams. check this for more info RN- params
Next you can store the id in async storage and retrieve it anywhere, I would suggest this cause is the easiest rn--async storage
import AsyncStorage from '#react-native-async-storage/async-storage';
const storeData = async (value) => {
try {
await AsyncStorage.setItem('#storage_Key', value)
} catch (e) {
// saving error
}
}
// read
const getData = async () => {
try {
const value = await AsyncStorage.getItem('#storage_Key')
if(value !== null) {
// value previously stored
}
} catch(e) {
// error reading value
}
}
you can do it this way, do tell me if you're stuck

Trying to post data to MongoDB, get status code 200 but fail to post data

I am a newbie to programming.
Now, I am working on a MERN stack project, trying to post data to my mongoDB database, but failed after many attempts.
Database:
There are 2 collections, 'items' and 'users' in the same database. The schemas are as follows:
Item Schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const ItemSchema = new Schema(
{
entryDate: {
type: Date,
required: true
},
leaveDate: {
type: Date,
required: true
}
},
{
collection: 'items'
}
);
module.exports = Item = mongoose.model('Item', ItemSchema);
User Schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
// Create Schema
const UserSchema = new Schema({
userName: {
type: String,
required: true
},
Password: {
type: String,
required: true
}
});
module.exports = User = mongoose.model('users', UserSchema);
Front-end:
handleClick = (e) => {
const API_URL = 'http://localhost:5000/api/users/';
this.setState({
startDate: this.handleStartDate(e.target.value),
endDate: this.handleEndDate(e.target.value)
});
const newDate = {
startDate: this.state.startDate,
endDate: this.state.endDate
}
const data = JSON.stringify(newDate);
axios({
method: 'post',
url: API_URL + 'addnew',
data: data,
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Access-Control-Allow-Origin': '*',
"Accept": "application/json"
}
})
.then(response => {
if (response.status === 200) {
console.log('The status code is : ' + response.status);
}
})
.catch(err => {
console.log('-------Failed to add new data. Error occurred.-------');
});
};
Backend:
// #route POST api/items
// #desc Create An Item
// #access Public
router.post('/addnew', function(req, res) {
const newItem = new Item({
entryDate: req.body.entryDate,
leaveDate: req.body.leaveDate
});
console.log(newItem);
// save model to database
newItem.save(function(err) {
if (err) {
res.json({
success: false,
message: 'failed to post data'
})
} else {
res.json({
success: true,
message: 'success to post data'
})
}
})
});
I have tested the backend API with Postman, the status code is 200, but returns the error message, shown below as in the screenshot:
Screenshot of Postman
I am not sure where I went wrong, my guess is that data of the schema 'Item' could not be saved into the collection 'items', but I have no clue what I should do.
I will be really appreciated for every little help. Thanks in advance!
Try to change like this
const Item = require('path/to/ItemSchemas');
// #route POST api/items
// #desc Create An Item
// #access Public
router.post('/addnew', function(req, res) {
const newItem = new Item({
entryDate: req.body.entryDate,
leaveDate: req.body.leaveDate
});
console.log(newItem);
// save model to database. Since newItem hasn't been added to the db, we used Item.save instead
Item.save(newItem, function(err) {
if (err) {
// save to db failed!
res.status(500).json({
success: false,
message: err
})
} else {
res.json({
success: true,
message: 'success to post data'
})
}
})
});

How can I catch the mongodb error to pass the test in jest?

I create a user schema using mongoose.
/src/server/models/User.ts:
import { model, Schema } from "mongoose";
export const UserSchema = new Schema({
address: {
type: String,
},
email: {
required: true,
type: String,
unique: true,
},
name: {
required: true,
type: String,
unique: true,
},
});
const User = model("User", UserSchema);
export default User;
I try to test the insertion of a user object that missed the name in order to get an error returned back from mongodb:
/src/tests/db.spec.ts:
import { MongoMemoryServer } from "mongodb-memory-server";
import mongoose, { Model } from "mongoose";
import { UserSchema } from "../server/models/User";
let mongoServer: MongoMemoryServer;
const opts = {
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
};
describe("Users", () => {
let User: Model<any>;
beforeAll(async () => {
mongoServer = new MongoMemoryServer();
const mongoUri = await mongoServer.getConnectionString();
const db = await mongoose.connect(mongoUri, opts);
User = db.model("User", UserSchema);
});
afterAll(async () => {
await mongoose.disconnect();
await mongoServer.stop();
});
describe("User Creation", () => {
it("Should returns an error if a name is missing", async () => {
const newUser = new User({
address: "address",
email: "user#gmail.com",
});
const createdUser = await User.create(newUser);
expect(createdUser).toThrow("User validation failed");
});
});
});
The test failed and I got this error:
● Users › User Creation › Should returns an error if a name is missing
ValidationError: User validation failed: name: Path `name` is required.
at new ValidationError (node_modules/mongoose/lib/error/validation.js:31:11)
at model.Object.<anonymous>.Document.invalidate (node_modules/mongoose/lib/document.js:2413:32)
at p.doValidate.skipSchemaValidators (node_modules/mongoose/lib/document.js:2262:17)
at node_modules/mongoose/lib/schematype.js:1058:9
How can I fix that?
According to jest/rejects, I used rejects to pass my test:
it("Should returns an error if a name is missing", async () => {
const newUser = new User({
address: "address",
email: "user#gmail.com",
});
await expect(User.create(newUser)).rejects.toThrow("Path `name` is required")
});

How create relationship between two collections

I'm creating server app using nodejs(express) and mongodb(mongoose). I must create relationships between Organization model and Users model. After creating an organization, I want to create a user that will apply to a specific organization. One user can apply to many organizations. How can I do this?
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// UserShema
const UserSchema = Schema({
login: {
type: String,
require: true,
unique: true
},
password: {
type: String,
require: true
},
organization: {
ref: "Organization",
type: Schema.Types.ObjectId
}
});
// Organization Schema
const OrganizationSchema = Schema({
label: {
type: String
},
users: [{
type: Schema.Types.ObjectId,
ref: "Users"
}]
});
//For now I have simple route for creating an Organization.
// request:
// {
// "label": "testOrg"
// }
exports.createOrganization = async (req, res) => {
try {
const org = await new Organization(req.body);
await org.save();
} catch (error) {
return res.status(500).json({error})
}
}
//And I have this route for user registration
exports.signup = async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
};
const {login} = req.body;
try {
const checkUser = await Users.findOne({login});
if (!checkUser) {
const user = await new Users(req.body);
await user.save();
return res.status(200).json({ user });
} else {
return res.status(400).json({error: "User already exist"})
}
} catch (error) {
return res.status(500).json({error})
}
};
You could embed the organization id into a string into the user document
Like this {
name: "Name",
location: "CA",
organizations: [123456789, 234567890, ...]
}

Mongoose - how to move object to another collection

My db include following collections:
users
deleted_users
My code is following:
const name = { type: String, required: true, index: { unique: true } };
const UserSchema = new mongoose.Schema({ name });
const DeletedUserSchema = new mongoose.Schema({ name }, {
versionKey: 'version',
});
const UserModel = mongoose.model('User', UserSchema);
const DeletedUserModel = mongoose.model('Deleted_user', DeletedUserSchema);
router.put('/:id/move', (req, res) => {
UserModel.findOne(
{ _id: id }
).then((user) => {
if (!user) {
return fail(...);
}
console.log(`moving user width id ${id}`);
const newUser = new DeletedUserModel(user);
return newUser.save()
.then(
() => {
console.log('ok');
})
.catch((err) => {
console.log('catch err ', err);
});
});
}
but I always receive
{ Error
at model.wrappedPointCut [as save] (/~/prj/node_modules/mongoose/lib/services/model/applyHooks.js:111:29)
at UserModel.findOne.then (/~/prj/src/routes/user/index.js:123:20)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
message: 'No matching document found for id "58dd804c434bdc1848d491cd"',
name: 'VersionError' }
Can you check that this id you are querying is not a String but an ObjectId because I think you are passing a String as id.