I'm trying to push data to a nested array in mongodb. I'm using mongoose as well.
This is just mock code to see if i can get it working:
User model:
import mongoose from "mongoose";
const CoinSchema = new mongoose.Schema({
coinID: { type: String },
});
const CoinsSchema = new mongoose.Schema({
coin: [CoinSchema],
});
const WatchlistSchema = new mongoose.Schema({
watchlistName: { type: String },
coins: [CoinsSchema],
});
const NameSchema = new mongoose.Schema({
firstName: { type: String },
lastName: { type: String },
username: { type: String },
});
const UserSchema = new mongoose.Schema({
name: [NameSchema],
watchlists: [WatchlistSchema],
test: String,
});
const User = mongoose.model("User", UserSchema);
export default User;
route:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
const updatedUser = await User.findByIdAndUpdate(id, {
$push: { "watchlists[0].coins[0].coin": newCoin },
});
await updatedUser.save();
// console.dir(updatedUser, { depth: null });
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});
request.body // "coinID": "test"
I've tried a lot of different ways to push this data but still no luck. I still get 201 status codes in my terminal which indicates something has been pushed to the DB, but when I check nothing new is there.
Whats the correct way to target nested arrays and push data to them?
It's not perfect but you could get the user document, update the user's watchlist, and then save the updated watchlist like so:
fastify.put("/:id", async (request, reply) => {
try {
const { id } = request.params;
const newCoin = request.body;
// get the user
let user = await User.findById(id);
// push the new coin to the User's watchlist
user.watchlists[0].coins[0].coin.push(newCoin);
//update the user document
const updatedUser = await User.findOneAndUpdate({ _id: id },
{
watchlists: user.watchlists,
},
{
new: true,
useFindAndModify: false
}
);
reply.status(201).send(updatedUser);
} catch (error) {
reply.status(500).send("could not add to list");
}
});
Related
so I'm making a message count command with discord.js and MongoDB but the "messageCount" value just never gets created. I searched it up and looked at docs but I couldn't find what was wrong.
Codes:
message-counter.js file:
const mongo = require("mongoose")
const schema = require("./schemas/rank/message-count-schema")
module.exports = client => {
client.on('messageCreate', async (message) => {
const { author } = message
const { id } = author
mongo.connect(
process.env.MONGO_URI,
{ keepAlive: true }
)
const dataQuery = await schema.findOne({ _id: id })
if (!dataQuery) {
const newSchem = schema(
{
_id: id
},
{
$setOnInsert: { messageCount: 1 }
},
{
$inc: { messageCount: 1 }
},
{
upsert: true
}
)
await newSchem.save()
}
else {
dataQuery.updateOne(
{
$inc: { messageCount: 1 }
},
{
upsert: true
}
)
}
})
}
message-count-schema.js file:
const mongoose = require('mongoose');
const messageCountSchema = new mongoose.Schema({
_id: {
type: String,
required: true
},
messageCount: {
type: Number,
required: true
}
})
module.exports = mongoose.model('message-count', messageCountSchema);
Can someone tell me what's wrong and how to fix it? I'm not asking to be spoon fed, just what's wrong.
The thing is $setOnInsert is only valid for update operations when the upsert value is set to true. It exists in these methods => updateOne(), updateMany, findAndModify(). In this case, when it not an update operation, the $setOnInsert doesn't run which is why your data doesn't have the messageCount value.
Like caladan said before, and adding to that you need .findbyId() if you want to use _id, is your message count is per user or per guild?
if per user you can add to your schema a userID String item and use
const member = await message.mentions.members.first() || message.guild.members.cache.get(args[0]) || message.author;
const dataQuery = await schema.findOne({ UserID: member.id })
const messagecount = dataQuery.messageCount;
console.log(messagecount)
If per guild, you can add GildId item in your schema, and use:
const dataQuery = await schema.findOne({ GuildId: message.guild.id })
const messagecount = dataQuery.messageCount;
console.log(messagecount)
I am trying to insert data into MongoDB database but I get this error Cannot read property 'push' of undefined.
I can't understand what is the issue is here in my code. please help me with the solution. I am a Student and learning it.
here I am trying to push service into the category Model. for that, I have created a one to many relations between service and category. but I can't push the services into the category.
Schema design for category & Service =======
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const CategorySchema = new Schema({
name:{
type:String,
required:true
},
services:[
{
type:Schema.Types.ObjectId,
ref:'Service'
}
]
},{ timestamps:true })
const Category = mongoose.model("Cat", CategorySchema);
module.exports = Category;
service======
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const serviceSchema = new Schema({
title:{
type: 'String',
required: true
},
description:{
type: 'String',
required: true
},
image: {
type: 'String',
required: true
},
price: {
type: 'Number',
required: true
},
category: {
type:Schema.Types.ObjectId,
ref:'Cat'
}
})
const Service = mongoose.model("Service", serviceSchema);
module.exports = Service;
here is my service controller
postService:(req, res)=>{
const { title, price, description,category} = req.body;
const image = req.file.filename;
const service = new Service({
title,
price,
category,
description,
image,
});
service.save()
.then((service)=>{
const category = Category.findOneAndUpdate({_id: service.category})
category.services.push(service)
category.save()
console.log(category)
return res.redirect("/admin/services");
})
.catch((err) => {
console.log(err);
return res.redirect("/admin/services/create");
});
},
do like this:
postService: async(req, res)=>{
const { title, price, description,category} = req.body;
const image = req.file.filename;
const service = new Service({
title,
price,
category,
description,
image,
});
try {
await service.save()
let categoryModel = await Category.findById(category);//category should be an ObjectId
categoryModel.services.push(service)
await categoryModel.save()
return res.redirect("/admin/services");
} catch (err) {
console.log(err);
return res.redirect("/admin/services/create");
}
},
I have used the below code in my API to remove element from an array
deleteCommentLike: async(req, res) => {
const { error } = createComLikeValidation(req.body);
if (!error) {
const { user_id, comment_id } = req.body;
// const likeModel = new likeSchemaModel({user_id: user_id, post_id: post_id});
await commentlikeSchemaModel
.find({ user_id: user_id, comment_id: comment_id })
.remove();
let commenttData = await commentSchemaModel.findById(comment_id);
console.log(commenttData.usersLiked);
commenttData.likes = --commenttData.likes;
commenttData.usersLiked.remove(user_id);
await commenttData.save();
res.status(200).json({ error: false, data: "done" });
} else {
let detail = error.details[0].message;
res.send({ error: true, data: detail });
}
},
In here this one line is not working: commenttData.usersLiked.remove(user_id);. It doesn't give any error but the user_id is not removed from my database.
"use strict";
const mongoose = require('mongoose');
const Joi = require('joi');
var commentSchema = mongoose.Schema({
//other data
usersLiked: [{
type: mongoose.Types.ObjectId,
default: []
}],
//other data
}
var commentSchemaModel = mongoose.model('comments', commentSchema);
module.exports = {
commentSchemaModel,
}
In my mongodb it looks like below
I have alredy tried using it as commenttData.usersLiked.remove(mongoose.Types.ObjectId('user_id'));
but the result is same.
What can be the reason for this and how could I remove the value from the array ?
You should use an update operation:
commenttData.update({_id: mongoose.Types.ObjectId("5f099..")}, {$set: {usersLiked: yourUpdatedUsersLikedArray}})
The error you expect from remove() is missing as you trigger a js noop which is just ignored by the compiler.
Mongoose does not implement the attribute update operation the way you use it.
I am fairly new to this (using sequelize) and everything is new to me. The thing is that I can create and get users through my "users.model.js" but now I want to create a model called "data.model.js" to associate some data to a certain user.
So according to the sequelize docs, my associations should be the following:
Users.hasMany(Data)
Data.belongsTo(Users)
But when sequelize creates my tables, I don't have my foreign key in my data table.
I will share my code with you:
config file (config.js):
const Sequelize = require('sequelize');
const connection = new Sequelize('drglicemia', 'root', '', {
host: 'localhost',
dialect: 'mysql'
});
module.exports = connection;
data.model.js:
const sequelize = require('sequelize');
const db = require('../config/database');
const usersTable = require('./users.model')
let Data = db.define('tabeladados', {
dta: { type: sequelize.DATEONLY },
hora: { type: sequelize.DATE },
indiceglicemia: { type: sequelize.STRING },
insulina: { type: sequelize.STRING },
medicacao: { type: sequelize.STRING },
}, {
timeStamps: false, tableName: 'tabeladados'
});
//associates the dataTable table with the users
Data.associate = () => {
Data.belongsTo(usersTable)
}
module.exports = Data;
users.model.js:
const sequelize = require('sequelize');
const promise = require('bluebird')
const bcrypt = promise.promisifyAll(require('bcrypt'))
const db = require('../config/database');
const dataTable = require('./data.model')
let Users = db.define('utilizadores', {
username: { type: sequelize.STRING },
email: { type: sequelize.STRING },
password: { type: sequelize.STRING },
}, {
timeStamps: false, tableName: 'utilizadores',
});
//encrypts the password before submiting to the database
Users.beforeCreate((user, options) => {
return bcrypt.hash(user.password, 10)
.then(hash => {
user.password = hash;
})
.catch(err => {
throw new Error();
});
});
//validates the password submited by the user with the one encrypted in the database
Users.prototype.validPassword = async (password) => {
return await bcrypt.compare(password, this.password);
}
//associates the users table with the dataTable
Users.associate = () => {
Users.hasMany(dataTable)
}
module.exports = Users;
I believe that when I am trying to associate my tables I am doing something wrong, because I feel that I am doing it the wrong way.
I don't know but everything works besides this.
But it's like what I said in the beginning, I am new to sequelize xD
I think the reason is circular reference. user.model.js requires data.model.js, and data.model.js requires user.model.js.
You need to create an index.js file. Require and make the associations for all models here, then re-export them. E.g.
./models/index.js:
const User = require('./user.model.js');
const Data = require('./data.model.js');
User.hasMany(Data);
Data.belongsTo(User);
module.exports = {User, Data}
service.js or controller.js:
const models = require('./models/index.js');
// use models
await models.User.findAll();
Remove below codes in your model file:
// Remove from user.model.js file
Users.associate = () => {
Users.hasMany(dataTable)
}
// Remove from data.model.js file
Data.associate = () => {
Data.belongsTo(usersTable)
}
I do not understand what the problem is.
And why each element from the 'tasks' array is null.
Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
tasks: [{type: Schema.Types.ObjectId, ref: 'Task'}]
}
);
const taskSchema = new Schema({
title: String
});
const User = mongoose.model('User', userSchema);
const Task = mongoose.model('Task', taskSchema);
// Add some default to DB
const task1 = new Task({
title: "Welcome! Here You Can:"
});
const task2 = new Task({
title: "ADD EDIT DELETE SHARE your TASKS "
});
const defaultTasks = [task1, task2];
When create new User I Add defaultTasks
const newUser = {
email: req.body.email,
password: req.body.password,
tasks: defaultTasks
};
Get Users Tasks
app.get('/tasks/', function(req, res){
const email = req.query.user;
User
.findOne({email: email})
.populate('tasks')
.exec()
.then(foundUser => {
console.log(foundUser);
const data = [];
Object.keys(foundUser.tasks).forEach(function(key) {
const val = foundUser.tasks[key];
data.push([val.title, val._id]);
});
res.send(data);
console.log('Data to send ' + data);
});
});
Before .Populate() console.log {
{ tasks: [ 5cf78ac1d08ee617fc89f7ed, 5cf78ac1d08ee617fc89f7ee ]
After { { tasks: [],
Please Help! All that I found did not solve my problem.
Maybe problem in defaultTasks. But i dont see it.
Your code doesn't save your task to DB, it just creates an object. So later when you populate User there are no tasks in DB to be found.
const task1 = await new Task({
title: "Welcome! Here You Can:"
}).save();
// or
const task1 = await Task.create({
title: "Welcome! Here You Can:"
});
P.s. of course you can deal with asynchronous calls the way you want.