Mongoose findByIdAndUpdate failed when trying to update - javascript

I am trying to update an Object, with new array data. I receive the message:
"MongooseError [CastError]: Cast to ObjectId failed for value "" at
path "playlistContent" "
And I receive "undefined".
When I console.log my array data, everything is fine, but I am not able to update my document, and I can't figure out why.
Here is my code:
router.post("/addspot/:id", async (req, res) => {
// Constants
let specficPlaylist = await Playlist.findById(req.params.id);
let spotFrequency = req.body.spotFrequency;
let spotAllocate = req.body.spotAllocate;
let populatedPlaylists = [];
await specficPlaylist.populate("playlistContent").execPopulate();
// For loop for passing in data in the right order
for (let i = 0; i < specficPlaylist.playlistContent.length; i++) {
if (i % spotFrequency == 0) {
populatedPlaylists =
populatedPlaylists + spotAllocate + ",";
}
populatedPlaylists =
populatedPlaylists +
specficPlaylist.playlistContent[i]._id+ ",";
}
// Array of data which I want to update my Object with
const playlistData = populatedPlaylists.split(",");
// Trying to update my specific document with the above data, but it fails
await Playlist.findOneAndUpdate(
{ _id: specficPlaylist._id},
{ playlistContent: playlistData },
{ new: true},
(err, docs) => {
}
);
res.redirect('back');
});
Can anybody help me out, how to pass the data the correct way, and then update my Playlist Object?
// My Schema:
const mongoose = require("mongoose");
const playlistSchema = new mongoose.Schema({
playlistName: {
type: String,
trim: true,
},
playlistDescription: {
type: String,
trim: true,
},
playlistUrl: {
type: String,
trim: true,
},
playlistContent: [{ type: mongoose.Schema.Types.ObjectId, ref: "Media" }],
playlistCreator: {
type: String,
trim: true,
},
});
mongoose.model("Playlist", playlistSchema);

Related

Error schema.find() is not a function when execute function

When Im trying to execute a function and using mongoose to find values in collection I get error find() is not a function
I use require on my schema in the top of the component before the function
const resModel = require('../Backend/ResourcesModel')
const getResources = () => {
const cookie = document.cookie;
const token = cookie && cookie.split('=')[1];
const decode = JSON.parse(Buffer.from(token.split('.')[1], 'base64'));
const para = {UserId:decode.user_id};
console.log(para);
resModel.find(para)
.select('Food Marble Gold Solfour')
.then(result => console.log(result))
}
Model:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const ResourcesTemple = new Schema({
UserId: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
Gold: {
type: String,
required: true
},
Solfour: {
type: String,
required: true
},
Marble: {
type: String,
required: true
},
Food: {
type: String,
required: true
}
}, {versionKey: false});
const Resources = mongoose.model('Resources', ResourcesTemple);
module.exports = Resources;
Error:
Uncaught TypeError: e.find is not a function

How to push data with Mongoose to a nested array in MongoDB

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

Mongoose - model.find is not a function

this is a very odd one that I don't quite understand why it's not working. I have 2 functions, one to add an item to a MongoDB collection. That is working fine. I have another function which is meant to search the collection for items matching my query. For some reason, the search function is returning 'not a function' and I'm wondering if anyone can help?
When I try and call findSimilarEvents() I get TypeError: event.find is not a function back in the console
My model:
var mongoose = require('mongoose');
const eventSchema = new mongoose.Schema({
eventTime: { type: Date, default: Date.now() },
eventLoggedFrom: String,
eventData: Object,
eventID: String,
ticketID: { type: String, default: "" },
ticketStatus: { type: String, default: "" },
eventLastUpdated: { type: Date, default: Date.now() },
})
module.exports = mongoose.model('event', eventSchema);
My working function:
exports.addEventToDB = async function(eventData, eventLoggedFrom, EventID) {
const event = new EventModel({
eventLoggedFrom: eventLoggedFrom,
eventData, // this is a JSON object
eventID: eventID
});
await event.save();
}
My non-working function:
exports.findSimilarEvents = async function(eventData, eventLoggedFrom) {
const event = new EventModel();
let similarEvents = await event.find({
eventData: eventData
});
for (var i = 0; i = similarEvents.length; i++) {
console.log("found similar event");
console.log(similarEvents[i]);
}
}
I'm happy to provide any other info if anyone has any thoughts!
Thank you in advance
exports.findSimilarEvents = async function(eventData, eventLoggedFrom) {
let similarEvents = await EventModel.find({
eventData: eventData
});
for (var i = 0; i = similarEvents.length; i++) {
console.log("found similar event");
console.log(similarEvents[i]);
}
}
try this ...

remove array element with remove() is not working?

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.

How to implement auto increment for mongodb in strapi?

i tried adding these mongoose plugins mongoose-auto-increment and mongoose-sequence to strapi in config/functions/mongoose.js.. the counter collections are getting created.. but the sequence counts are not getting updated.. Is there a way to get these plugins working or is there a way to implement it myself?
// config/functions/mongoose.js
var autoIncrement = require('mongoose-auto-increment');
module.exports = (mongoose, connection) => {
autoIncrement.initialize(mongoose.connection);
var movieSchema = mongoose.Schema({
title: String
}, { collection : 'Tests' });
movieSchema.plugin(autoIncrement.plugin, { model: 'Test', field: 'movieId', startAt: 1 });
};
In a similar situation I solved it using a new Schema as a Counter for the Ids.
Here is the Counter Schema (models/counter.js):
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CounterSchema = Schema({
_id: {
type: String,
required: true
},
sequence: {
type: Number,
default: 0
}
}, {
collection: 'counters'
});
// export the counter model below and call this method to create the first entry in the counter's table
CounterSchema.statics.createFirstIdForMovie = async () => {
const newCounter = new counter({
_id: "movieid",
sequence: 0
});
newCounter.save();
}
And the Movie Schema would be (models/movie.js):
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const MovieSchema = new Schema({
...,
identifier: {
type: Number,
required: false,
unique: true
},
...
});
MovieSchema.pre('save', async function (next) {
// get the next value for the identifier of 'movieid'
if (this.identifier) {
// just editing, don't need to increment or set a new identifier
return;
}
let c = await counter.findById('movieid');
if (!c) {
c = await counter.createFirstIdForMovie();
}
c.sequence += 1;
await c.save();
this.identifier = c.sequence;
});
Hope it helps!
My workaround was to use a single-type as counter.
Each time I need to use and increment the counter I get the counter single-type and use the built-in createOrUpdate service to get the number.
const counters = await strapi.services.counters.find();
const updatedCounter = await strapi.services.counters.createOrUpdate({
ainumber : counters.ainumber + 1,
});
I know single-types are not ment for this, but it works and is easy to handle.
Hope helps someone

Categories