Mongoose allowing duplicates with unique constraint added - javascript

I am trying to avoid duplicates from being saved in the system, and have implemented the model like so...
var mongoose = require('mongoose'),
ObjectId = mongoose.Schema.Types.ObjectId,
Schema = mongoose.Schema;
var User = require('../models/user.js');
var Stamp = new Schema({
name: {type: String, unique: true },
creatorId: {type: ObjectId, ref: 'User'},
dateAdded: {type: Date}
}, {collection: "stamps"});
Stamp.index({name: 'text'});
//to avoid duplicate names
Stamp.path('name').index({ unique: true });
module.exports = mongoose.model('Stamp', Stamp);
The code for saving the new stamp:
var new_stamp = new Stamp ({
name: stampname,
creatorId: creatorId,
dateAdded: dateAdded
});
new_stamp.save(function(err, results){
if(!err) {
console.log('stamp has been added to the db');
} else {
console.log("Error creating stamp " + err);
}
});
How do I stop from duplicates being saved?

Related

Mongoose populate replacing ObjectIds with empty array

I've been trying to use the mongoose populate function to connect two models. I can save an object but when trying to retrieve using populate the ObjectIds are just replaced with an empty array.
Many questions seem to have been asked but none have a solution that worked for me
user.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Route = require('./route')
var passportLocalMongoose = require('passport-local-mongoose');
const postSchema = new Schema ({
text: {
type: String,
default: '',
required: true
}
}, {
timestamps: true
});
const UserSchema = new Schema({
firstname: {
type: String
},
posts: [postSchema],
route: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Route'
}]
}, {
timestamps: true
});
UserSchema.plugin(passportLocalMongoose);
const User = mongoose.model('User', UserSchema);
module.exports = User;
route.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
const locationSchema = new Schema ({
id: {
type: Number,
default: 0,
required: true
},
address: {
type: String,
default: '',
required: true
},
lat: {
type: Number,
default: 0,
required: true
},
lng: {
type: Number,
default: 0,
required: true
}
},{
timestamps: true })
const routeSchema = new Schema ({
locations: [locationSchema],
description: {
journey1: {
type: String,
default: '',
required: false
},
journey2: {
type: String,
default: '',
required: false
},
journey3: {
type: String,
default: '',
required: false
},
journey4: {
type: String,
default: '',
required: false
}
}
}, {
timestamps: true
});
module.exports = mongoose.model('Route', routeSchema);
within REST POST end point
User.findOne({_id: req.user._id}, function(err,user) {
if(user) {
var routed = new Route();
routed.locations = req.body.locations;
routed.description = req.body.description;
user.route.push(routed);
user.save()
.then((user) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json')
res.json(user)
}, (err) => next(err))
} else {
console.log("errored")
err = new Error('User ' + req.body.username + ' not found');
err.status = 404;
return next(err);
}
})
within REST GET end point
User.findOne({_id: req.user._id})
.populate('route')
.then((user) => {
if(user){
console.log("user")
console.log(user)
console.log("routes")
console.log(user.route)
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json')
res.json({success: true, routes: user.route});
}
}, (err) => next(err))
.catch((err) => next(err));
If I remove populate I'll get something like
[
new ObjectId("61f053af7ba46267f4893f8f")
new ObjectId("61f053af7ba46267f4893f8f")
new ObjectId("61f053af7ba46267f4893f8f")
]
from the GET end point but adding it back in returns
[].
My understanding is that in 'new Route()' I'm creating a new Route Object with an Id that gets stored in the User model/document(?). Then when I call populate mongoose searches the Route document for those Ids and converts them to the objects I want. The only issue I could think of is that I'm not creating the Route objects correctly and so no object is being stored with that Id which is why an empty array is returned when I come to try swap Ids with Route objects.
Any ideas or are we all just stumbling in the dark ?
Not entirely sure this is the correct method but instead of instantiating a Route object as displayed I used the Route.create(...) method and then pushed that to the route array and now populate works as expected

findout a chat room by owner ids Mongoose

I am trying to find out a chat room with two owners (sender and receiver) from DB. if such a chat room is not there one has to be created with ids provided and a name
i am trying to create a chat app with user login and db storage.
//Mongoose Schema
const chatRoomSchema = new mongoose.Schema({
room:{
type: String,
trim:true,
required:true
},
owners:[{
owner:{
type:mongoose.Schema.Types.ObjectId,
required:true,
ref:'User'
}
}]
},{
timestamps:true
})
const ChatRoom = mongoose.model('Chatroom',chatRoomSchema)
//what i tried
const id1 = req.params.id1
const id2 = req.params.id2
let chatroom = ChatRoom.find({owners:{$all:[{owner:id1}, {owner:id2}]}})
if(!chatroom){
console.log('no chat room')
chatroom = new ChatRoom({room:'123', owners:[{owner:id1},{owner:id2}]})//creating a new chatroom
chatroom.save()
res.send(chatroom)
}
i am trying to find out a chat room with two owner ids. if there is no such chat room we have to create one with both ids as owners
You want an array of owner ids, not owner objects, so change:
owners:[{
owner:{
type:mongoose.Schema.Types.ObjectId,
required:true,
ref:'User'
}
}]
to
owners:[{
type:mongoose.Schema.Types.ObjectId,
required:true,
ref:'User'
}]
you can find room with 2 owners like:
var arr = ['5d6bd3b374068124c461975a', '5d6bd3b374068124c4619759']
ChatRoom.find({owners:{$all:arr}}, (err, room) =>{...}
full sample project:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const init = false
mongoose.connect('mongodb://127.0.0.1/stackoverflow_play5')
//Mongoose Schema
const userSchema = new Schema({
username: String
})
const chatRoomSchema = new mongoose.Schema({
room:{
type: String,
trim:true,
required:true
},
owners:[{
type:mongoose.Schema.Types.ObjectId,
required:true,
ref:'User'
}]
},{
timestamps:true
})
const ChatRoom = mongoose.model('Chatroom',chatRoomSchema)
const User = mongoose.model('User',userSchema)
if(init){
User.insertMany([{username: 'yaya'}, {username: 'hoho'}, {username: 'mil'}], (err, users) => {
ChatRoom.insertMany([{room: 'r1', owners: [users[0]._id, users[1]._id]}], (err, chatrooms) => console.log('done.'))
})
}else{
//ChatRoom.find({}, (err, users)=>{console.log(users)})
var arr = ['5d6bdfe9c0d0af00ec68932c', '5d6bdfe9c0d0af00ec68932d']
ChatRoom.find({owners:{$all:arr}}, (err, room) =>{
console.log(room)
})
}
You can change room to be auto generated by mongoo, and instead of find then create if not found you can use findOneAndUpdate
const chatRoomSchema = new mongoose.Schema({
room:{
type: mongoose.Schema.Types.ObjectId,
auto: true
},
owners:[{
owner:{
type:mongoose.Schema.Types.ObjectId,
required:true,
ref:'User'
}
}]
},{
timestamps:true
})
const ChatRoom = mongoose.model('Chatroom',chatRoomSchema)
//what i tried
const id1 = req.params.id1
const id2 = req.params.id2
const options = { upsert: true, new: true, setDefaultsOnInsert: true };
let chatroom = ChatRoom.findOneAndUpdate(
{owners:{$all:[{owner:id1}, {owner:id2}]}},
{ owners:[{owner:id1},{owner:id2}] } ,
options, function(error, result) {
if (error) return;
// do something with the document
});

Issue with adding comment

I am making a node API. I am stuck at adding a comment to a story.
I am able to create a comment but instead of pushing it to a given story, it was trying to create a new instance of story.
Story.findOne(req.params.id, (err, foundstory) => {
if(err){
res.status(500).json({msg:err})
}else{
let comment = new Comment()
comment.body = req.body.body
comment.author = req.body.author
console.log(foundstory)
//save comment//
comment.save((err, comment) => {
if(err){
res.status(500).json({msg:err})
}else{
//pushing comment to comments array (ref) in story
foundstory.comments.push(comment)
foundstory.save()
res.status(200).json({msg:"Comment saved"})
}
})
}
})
Story Schema
import mongoose from 'mongoose'
import User from './user'
import Comment from './comment'
const Schema = mongoose.Schema
const ObjectID = mongoose.Schema.Types.ObjectId
const storySchema = new Schema({
//subdoc ref from user
author: {type: ObjectID, ref: 'User'},
//subdoc ref from comment
comments: [{
type: ObjectID,
ref: 'Comment'
}],
//contents of story//
title: {type: String, required: true},
body: {type: String, required: true},
date: {type: Date, default: Date.now()},
tags: [{type: String}]
})
module.exports = mongoose.model('Story', storySchema)
Comment Schema
import mongoose from 'mongoose'
import User from './user'
const Schema = mongoose.Schema
const ObjectID = mongoose.Schema.Types.ObjectId
const commentSchema = new Schema({
body : {type: String, required: true},
author: {type: ObjectID, ref: 'User'}
})
module.exports = mongoose.model('Comment', commentSchema)
I have an array of type "Comment" in my "Story" schema. My attempt is to push those comment to that array.
try changing your code like this:
Story.findById(req.params.id, (err, foundstory) => {
if (err) res.status(500).json({
msg: err
});
else if (!foundStory) res.status(400).json({
msg: "Story Not Found"
});
else {
let comment = new Comment();
comment.body = req.body.body;
comment.author = req.body.author;
//save comment//
comment.save(async (err, comment) => {
if (err) res.status(500).json({
msg: err
});
else {
foundstory.comments.push(comment._id);
await foundstory.save();
res.status(200).json({
msg: "Comment saved"
})
}
})
}
})
I've changed the findOne() method with findById(), also the 'foundstory.save()' method is an asynchronous call, so i used async\await to handle it.
Hope this helps :)

MongoDb relations not connected with other

I am writing a cook book in node.js. Im new to this language and mongoDB concept. I identify that I need to have a user who has favorite recipes nad in favorite recipes I am going to store recipes
My model look like that and something its wrong here
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
userSchema = new Schema({
name: String,
userId: {type: String, required: true},
favorites: [{
type: Schema.Types.ObjectId,
ref: 'Favorites',
}],
});
favoritesSchema = new Schema({
name: String,
id: {type: Schema.Types.ObjectId},
recipes: [{
type: Schema.Types.ObjectId,
ref: 'Recipes',
}],
startOfRecipe: {type: Date},
});
recipeSchema = new Schema({
name: {type: String, unique: true},
});
const User = mongoose.model('User', userSchema);
const Favorites = mongoose.model('Favorites', favoritesSchema);
const Recipes = mongoose.model('Recipes', recipeSchema);
module.exports = {User, Favorites, Recipes};
I wrote a function which looking for user and then store favorite recipe
addFav(fav, userId) {
return new Promise(function(resolve, reject) {
schema.User.findOne({userId: userId}, function(err, user) {
if (err || !user) {
} else {
schema.Favorites.create({
name: fav,
}, (err, result) => {
if (err) throw err;
console.log(result);
resolve('noResult');
});
resolve(user);
}
});
});
}
and it saves but if I call my user the array favorites is always empty
{ favorites: [],
_id: 5cb32867d2dfea0cadd79ecb,
name: 'Anna',
userId:
'AF322',
__v: 0 }
What am I doing wrong? Could someone help me please :)
Please check below code. I created subschema of favorites & recipes, get user details using userId and push favorites object into favorites field
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
userSchema = new Schema({
name: String,
userId: {type: String, required: true},
favorites: [favoritesSchema],
});
favoritesSchema = new Schema({
name: String,
id: {type: Schema.Types.ObjectId},
recipes: [recipeSchema],
startOfRecipe: {type: Date},
});
recipeSchema = new Schema({
name: {type: String, unique: true},
});
const User = mongoose.model('User', userSchema);
addFav(fav, userId) {
return Schema.User.update({_id:userId}, {$set:{$push:{favorites:fav}}})
}

Mongoose .save fails

I learning node.js & mongoDB & mongoose, from maybe a week or 2. The problem I have right now is, I'm trying to save to db via mongoose .save(), but it doesn't work as expected. I'm watching a tutorial, and it's 3 days old, so should be up to date, but I'm getting strange error.
mpromise (mongoose's default promise library) is deprecated” error when testing [duplicate]
I read, here on stackoverflow that I can just add:
mongoose.Promise = require('bluebird');
It will work, but the code doesn't even go to the .save function, and don't trow an error. I'm not sure where the problem is.
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
let connectionString = 'mongodb://localhost:27017/mongo2';
mongoose.createConnection(connectionString, (err) => {
if (err) {
console.log(err);
return;
}
let Student = mongoose.model('Student', {
firstName: {type: String, required: true},
lastName: {type: String, required: true},
age: {type: Number},
facultyNumber: {type: String, unique: true}
});
let me = new Student({
firstName: 'Who',
lastName: 'amI',
age: 20,
facultyNumber: '9374823104'
});
me.save().then((info) => {
console.log(info);
}).catch((error) => {
console.log(error);
});
});
Edit: The result is: Getting the DB created, the collection too, but not the object. Everything is empty.
Very likely the problem is that your model does not have a schema attached.
const { Schema } = require('mongoose');
const StudentSchema = new Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
age: {type: Number},
facultyNumber: {type: String, unique: true}
}};
let Student = mongoose.model('Student', StudentSchema);

Categories

Resources