findout a chat room by owner ids Mongoose - javascript

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
});

Related

How to insert data into MongoDB collection?

I'm using NodeJS with Mongoose. I've two tables into db.js:
const mongoose = require('mongoose')
const UserSchema = new mongoose.Schema(
{
username: { type: String, required: true, unique: true },
email: { type: String, required: true, unique: true },
password: { type: String, required: true }
},
{ collection: 'users' }
)
const model = mongoose.model('UserSchema', UserSchema)
const AccountSchema = new mongoose.Schema(
{
username: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'hahaha' },
balance: { type: Number, required: true }
},
{ collection: 'accounts' }
)
module.exports.UserSchema = model
module.exports.AccountSchema = model
As you can see the first collection contains users (username, email, password). The second collection represents a bank account, related to a specific user. So, it has two fields: user (foreign key) and balance ($100, i.e.). First question: is my code correct to accomplish this task?
Second question: how can I insert data into the AccountSchema?
I obviously want to insert data only if the user exists into Userschema. I think that this doesn't work:
const Schema = require('./model/db')
app.post('/api/addaccount', async (req, res) => {
const { username, balance } = req.body
try {
const response = await Schema.AccountSchema.create({
username,
balance
})
console.log('User account successfully: ', response)
res.json({status : "ok"})
} catch (error) {
throw error
}
})
How can I do this?
This won't work. You've to query the User model first to check if any user exists with this username. If yes, you'll continue to store data in the Account model, if not you'll return a response something like user doesn't exist

Delete nested object with mongoose

I got this mongoose schemas:
const UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true,
},
groups: [
{
groupName: {
type: String,
required: true,
},
groupMembers: [{ type: Schema.Types.ObjectId, ref: "GroupMember" }],
},
],
});
const GroupMemberSchema = new Schema({
firstName: String,
lastName: String,
birthday: Date,
gender: String,
age: Number
});
I want to have 2 routes:
Delete a group member from the groupMembers array based on objectId.
Delete a whole group from the groups array based on objectId.
My attempt for the delete group member route. This route removes the group member from the groupMembers collection succesfully, but the group member still exist in the user collection:
router.delete(
"/:userId/:groupId/:groupMemberId",
catchAsync(async (req, res) => {
const { userId, groupId, groupMemberId } = req.params;
await GroupMember.findByIdAndDelete(groupMemberId);
const user = await User.findById(userId);
const group = user.groups.find((group) => group._id.toString() === groupId);
const groupIndex = user.groups.indexOf(group);
const updatedGroupmembers = user.groups[groupIndex].groupMembers.filter(groupMember=> groupMember._id.toString()!==groupMemberId);
res.send({updatedGroupmembers})
})
);
Did you try using $pull?
router.delete(
'/:userId/:groupId/:groupMemberId',
catchAsync(async (req, res) => {
const { userId, groupId, groupMemberId } = req.params;
await GroupMember.findByIdAndDelete(groupMemberId);
const updatedUser = await User.findByIdAndUpdate({ id: userId }, { $pull: { groups: groupId } }, { new: true });
res.send({ updatedUser });
}),
);

Can't pass multiple documents in an array when using findById

I want to find each of the elements in the array by their id and send it with the post request to create a new post. Right now when I create a new post only passes the first index of the array and if I use find() it passes all of the social schemas regardless if it is in the body of the request. I hope this makes sense if it doesn't please let me know. I hope someone can help.
Below is the mongoose schema for the qrcode post also using Joi
const Joi = require("joi");
const mongoose = require("mongoose");
const { themeSchema } = require("./Theme");
const { userSchema } = require("./User");
const { socialSchema } = require("./Social");
const QrCode = mongoose.model(
"QrCode",
new mongoose.Schema({
user: {
type: userSchema,
required: true,
},
name: {
type: String,
maxLength: 255,
required: true,
trim: true,
},
theme: {
type: themeSchema,
required: true,
},
// Social Media Links
social: [
{
type: socialSchema,
required: true,
},
],
})
);
function ValidateQrCode(qrCode) {
const schema = {
userId: Joi.objectId(),
name: Joi.string().max(255).required(),
themeId: Joi.objectId().required(),
socialId: Joi.array().required(),
};
return Joi.validate(qrCode, schema);
}
module.exports.QrCode = QrCode;
module.exports.validate = ValidateQrCode;
this is the post route to create a new qrcode
router.post("/", auth, async (req, res) => {
const { error } = validate(req.body);
if (error) res.status(400).send(error.details[0].message);
const theme = await Theme.findById(req.body.themeId);
if (!theme) return res.status(400).send("Invalid theme.");
const user = await User.findById(req.user._id);
if (!user) return res.status(400).send("Invalid theme.");
const social = await Social.findById(req.body.socialId);
if (!social) return res.status(400).send("Invalid social.");
const qrCode = new QrCode({
user: user,
name: req.body.name,
theme: theme,
social: social,
});
await qrCode.save();
res.send(qrCode);
});
In the body of my Postman request I am inputting the info below
{
"name": "Friends",
"themeId": "60f89e0c659ff827ddcce384",
"socialId": [
"60f89e43659ff827ddcce386",
"60f89e5c659ff827ddcce388"
]
}
To fetch data using ids, you can use below mongodb query simply,
db.collection.find( { _id : { $in : ["1", "2"] } } );
In mongoose,
model.find({
'_id': { $in: [
mongoose.Types.ObjectId('1'),
mongoose.Types.ObjectId('2'),
mongoose.Types.ObjectId('3')
]}
}, function(err, docs){
console.log(docs);
});
Or
await Model.find({ '_id': { $in: ids } });

How can I reach a value from an array and update it

I'm working at this project and I have users which have positive ranking. But I want to store others users id in an array which hit that "positive ranking button". I'm working with Mongoose and NodeJs.
I created the User Schema which contains the array and I searched for that user in my database, I get the user, but I'm stuck here, I don't know if I have to use a "for" to reach all array values or how do I check if the user has already "positive ranked" him.
This is my postPositiveRank function
exports.postPositiveRank = (req,res,next) =>{
const targetUser = req.body.targetUserId;
const loggedInUser = req.session.user._id;
User.findOne({"_id": targetUser}, function(err, process) {
for( let i = 0; i< process.positiveRanked.length;i++)
{
if(loggedInUser.equals(process.positiveRanked[i]))
{
//
}
else {
process.positiveRanked.push(loggedInUser);
process.positiveRanked.save();
}
}
})
}
And my User Schema
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
firstname: {
type: String,
required: true
},
lastname: {
type: String,
required:true
},
age: {
type: Number,
required:true
},
occupation: {
type: String,
required:true
},
city: {
type: String,
required: true
},
county: {
type: String,
required:true
},
country: {
type:String,
required: true,
},
email: {
type: String,
required:true
},
password: {
type: String,
required:true
},
imageUrl: {
type: String,
required:true
},
rate:{
type:Number,
required:true
},
positiveRanked: [],
negativeRanked: []
});
module.exports = mongoose.model('User', userSchema);
I want that loggedInUser to be searched on the array even if it's positiveRanking or negativeRanking and if it is found to get back on the page with a message (I handle that ), and if it's not found to be added to the array.
I appreciate if you can help me, I hope I explained well.
There is a typo in your schema for positiveRanked please change that. You can use findIndex method on arrays to getIndex of the user you want to search if found it will return the index of the user in that array if not it will return -1 by this way you can avoid using for loop. I suggest using async/await because this is the better approach where you can keep your code clean and robust. If it did not work please let me know
exports.postPositiveRank = (req,res,next) =>{
const targetUser = req.body.targetUserId;
const loggedInUser = req.session.user._id;
User.findOne({"_id": targetUser}, function(err, process) {
const index=process.postitiveRanked.findIndex(id=>id===loggedInUser)
if(index!==-1)
{
// user found
}
else{
process.positiveRanked.push(loggedInUser);
process.save()
}
})
}
Using Async/await
exports.postPositiveRank = async (req,res,next) =>{
const targetUser = req.body.targetUserId;
const loggedInUser = req.session.user._id;
try{
let user = await User.findOne({"_id": targetUser})
const index=user.postitiveRanked.findIndex(id=>id===loggedInUser)
if(index!==-1)
{
// user found
}
else{
user.positiveRanked.push(loggedInUser);
await user.save()
}
}
catch(error){
console.log(error)
}
}

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}}})
}

Categories

Resources