Why this code is creating two similar object in mongodb? - node.js

Node js
The method used to post the comment data
const { type, movieId, userId, review, timestamp } = req.body;
const movie = await Movie.findOneAndUpdate(
{ movieId: movieId, type: type },
{
$push: {
movieReview: { ... },
},
},
{ upsert: true, new: true },
(err, info) => {
...
}
);
Reactjs
The method used to submit the comment
const submit_comment = async () => {
....
const file = {
movieId: id,
type: type,
userId: userInfo._id,
comment: comment,
};
if (!commentFlag) {
const { data } = await axios.post("/api/movie/add-comment", file, config);
...
};
Mongoose Schema
const movieSchema = new mongoose.Schema({
movieId: String,
type: String,
...
comment: [{ type: mongoose.Schema.Types.ObjectId, ref: "Comment" }],
});
After I run my submit function it posts two objects with the same object _id in mongoDB

Related

Why deletion of element of embedded subdocument array using Mongoose JS isn't working?

1.) I have two models: Project and Action:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ProjectSchema = new Schema({
_id: Schema.Types.ObjectId,
title: { type: String, default: "default project title" },
deadline: { type: Date, default: "2099-01-01T10:30" },
description: { type: String, default: "default project description" },
actions: [],
});
module.exports = mongoose.model("Project", ProjectSchema);
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const ActionSchema = new Schema({
_id: Schema.Types.ObjectId,
type: { type: String, default: "none" },
queued: { type: Boolean, default: false },
description: { type: String, default: "default description" },
complete: { type: Boolean, default: false },
waitingFor: [],
setting: { type: String, default: "default setting" },
deadline: {type: Date, default: "2099-01-01T10:30"}
});
module.exports = mongoose.model("Action", ActionSchema);
2.) I have a service to destroy an Action which should both update Project actions subdocument array (i.e. delete the action) and delete the Action from its collection.
It receives an id of the Action to delete from the array.
3.) I've tried several approaches but the closest I've gotten is:
require("../db");
const mongoose = require("mongoose");
const Action = require("../models/action");
const Project = require("../models/project");
const destroy = async (id) => {
const filter = { _id: id };
const action_id = mongoose.Types.ObjectId(id);
const project_id = mongoose.Types.ObjectId("5fdcd4fdc0d61b7fe59f0940");
Project.updateOne(
{},
{
$pull: { actions: { _id: id } },
},
{
arrayFilters: [{ "i._id": mongoose.Types.ObjectId(id) }],
new: true,
}
).then((output => console.log("output of db op: ", output)))
Action.deleteOne(filter, function (err, output) {
console.log("output of db op ", output);
});
};
The deletion of Action from its collection works but Project does not update its actions array. Currently, the output of the above is:
output of db op: { n: 1, nModified: 0, ok: 1 } (It finds Project but doesn't update!
output of db op { n: 1, ok: 1, deletedCount: 1 } (Successfully deletes from Action collection, but Project array is unmodified)
Any suggestions for how to successfully update Project is much appreciated. Thanks!
The pull operator sometimes doesn't work properly in MongoDB so you can try it with an update and provide the ids directly as objectIDs in the query. Also, you need to provide the id of the project you are trying to update in the update one.
Project.update({ _id: ObjectId(project_id ) },
{ $pull: { actions: ObjectId(action_id ) } },
{ new: true }, function (err, source) {
if (!err) {
console.log('Source log',source);
Action.deleteOne(filter, function (err, output) {
console.log("output of db op ", output);
});
}
else{
console.log('Error in deleting projects and actions')
}
});

Feathersjs-Mongoose populate data

When using find method, how can populate data from other collection. The join operation that we do with sql databases. Right now i am using something like :
code:
async find(data, params) {
let records = await super.find(data, params);
let newrecords = records.data.map(async (user) => {
let professordetails = await this.app
.service("users")
.get(user.professorId);
professordetails.password = undefined;
user.professorId = professordetails;
return user;
});
return await Promise.all(newrecords).then((completed) => {
return completed;
});
}
This is course service and its model :
module.exports = function (app) {
const modelName = "courses";
const mongooseClient = app.get("mongooseClient");
const { Schema } = mongooseClient;
const { ObjectId } = Schema;
const schema = new Schema(
{
name: { type: String, required: true },
details: { type: String, required: true },
professorId: { type: ObjectId, ref: "users", required: true },
enrolledStudents: [{ type: ObjectId, ref: "users" }],
},
{
timestamps: true,
}
);
// This is necessary to avoid model compilation errors in watch mode
// see https://mongoosejs.com/docs/api/connection.html#connection_Connection-deleteModel
if (mongooseClient.modelNames().includes(modelName)) {
mongooseClient.deleteModel(modelName);
}
return mongooseClient.model(modelName, schema);
};
This is something like a unwanted operation as we are having populate. But i couldn't do it with populate.

Mongoose find nested object [duplicate]

This question already has answers here:
Mongoose Query to filter an array and Populate related content
(2 answers)
Find after populate mongoose
(3 answers)
Closed 3 years ago.
I know that there are similar questions to this one, but the answers to those have not yielded the correct result.
I want to query a nested object with mongoose find. This is what I currently have setup:
reportRoutes.route('/:id').get(async (req, res) => {
try{
let id = req.params.id
let author = req.params.author
let regex = new RegExp( id, 'i')
const report = await Report.find({title: regex, 'player.player_name': "James Harden" })
.populate({path: 'like'})
.populate({
path: 'player',
populate: [{ path: 'team' },
{
path: 'team',
populate: {
path: 'league'
}
}
]
})
res.json(report)
} catch (e) {
res.status(500).send()
}
})
When I run this in postman, I receive a blank array.
This is the route that query string that I'm using: localhost:4000/reports/harden
This is the schema for Report:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
let Report = new Schema({
title: {
type: String
},
summary: {
type: String
},
analysis: {
type: String
},
source_title: {
type: String
},
source_link: {
type: String
},
author: {
type: String
},
like: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Like'
}],
player: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Player'
}
}, { timestamps: true })
module.exports = mongoose.model('Report', Report)
And this is the schema for player:
const mongoose = require('mongoose')
const Schema = mongoose.Schema
let Player = new Schema({
player_name: {
type: String
},
player_position: {
type: String
},
team: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'Team'
}
}, { timestamps: true })
module.exports = mongoose.model('Player', Player)
Since you are using populate try using the match stage:
reportRoutes.route('/:id').get(async (req, res) => {
try{
let id = req.params.id
let author = req.params.author
let regex = new RegExp( id, 'i')
const report = await Report.find({ title: regex })
.populate({path: 'like'})
.populate({
path: 'player',
match: { 'player_name': 'James Harden'}, // <-- match here
populate: [{ path: 'team' },
{
path: 'team',
populate: {
path: 'league'
}
}]
})
res.json(report)
} catch (e) {
res.status(500).send()
}
})
Documentation on this can be found here

Adding field with migration on mongoDB

So I tried to migrate a new field to the mongoDB collections.
New field is a array that is filled with objects.
The migration runs and is successful, it even shows the new field when
looking the collections.
Problem comes when I try to add data to this field - it shows that the
field is undefined.
What should be done to overcome this problem?
Migration code:
exports.up = async function(db) {
await db
.collection('useractions')
.update({}, {
$set: {
history: []
}
}, {multi: true, upsert: false});
};
Code to populate the new field:
const bookId = req.body.bookId;
const timestamp = req.body.timestamp;
const userId = req.body.userId;
const container = {bookId, timestamp};
UserAction.update(
{ userId },
{$set: { history: container}},
(err, cb) => {
if(err)next({error: err});
res.status(200).json({
cb
})
})
EDIT:
Schema:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userActionModel = new Schema({
userId: {
type: String
},
likes: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Podcast',
default: []
}],
tags: {
type: [String],
default: []
},
orderedBook: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Show',
default: []
}]
})
module.exports = mongoose.model('userAction', userActionModel);

Mongoose can't push new obejct to parent array

I've got the following mongoose models:
Place.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const placeSchema = new Schema({
title: { type: String, require: true },
filename: { type: String, require: true },
lociSets: [{ type: Schema.Types.ObjectId, ref: 'LociSet'}]
})
module.exports = mongoose.model("places", placeSchema)
LociSet.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const LociSchema = require('./Locus')
const lociSetSchema = new Schema({
title: { type: String, require: true },
creator: { type: Schema.Types.ObjectId, ref: 'User' },
public: { type: Boolean, default: true },
loci: [LociSchema]
})
module.exports = mongoose.model("lociSets", lociSetSchema)
Locus.js
const mongoose = require("mongoose")
const Schema = mongoose.Schema
const locusSchema = new Schema({
position: {
x: { type: Number, require: true },
y: { type: Number, require: true },
z: { type: Number, require: true }
}
})
module.exports = locusSchema
Problem:
I try to insert a new LociSet into the lociSet array of Place like so:
exports.createOne = async (req, res) => {
const {
title,
public = true,
loci = []
} = req.body
console.log(title,public,loci,req.user.id)
const lociSet = new LociSet({
title,
public,
loci,
creator: req.user.id
})
try {
const place = await Place.findOne({
"title": req.params.title.toLowerCase()
})
console.log(lociSet)
await lociSet.save()
await place.lociSets.push(lociSet)
await place.save()
} catch (err) {
res.status(500).send({
message: "Some error occurred while creating the loci set.", err
});
}
}
But then I get an error message saying "Cast to [undefined] failed for value \"[{\"title\":\"Test set\",\"creator\":\"5a7898c403999200c4ee3ae5\",\"public\":\"true\"}]\" at path \"lociSets\""
The LociSet model is created without problems, but it seems to break when I try to save the place model
Because lociSets is an array of ObjectId references, you may want to try the following approach:
exports.createOne = async (req, res) => {
const { title, public = true, loci = [] } = req.body
const lociSet = new LociSet({
title,
public,
loci,
creator: req.user.id
})
try {
const newLociSet = await lociSet.save()
const place = await Place.findOneAndUpdate(
{ "title": req.params.title.toLowerCase() },
{ "$push": { "lociSets" : newLociSet._id } },
{ "new": true}
)
res.status(200).json(place)
} catch (err) {
res.status(500).send({
message: "Some error occurred while creating the loci set.", err
})
}
}

Resources