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);
Related
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
I need your help please with a mongoose query for my express app.
I have 3 collections Movies, TvShows and Trailers and I need to fetch all movies or shows that have trailers.
here are the models:
var TrailerSchema = new Schema(
{
link: {
type: String,
required: true,
},
movieId: { type: mongoose.Schema.Types.ObjectId, ref: 'Movie' },
showId: { type: mongoose.Schema.Types.ObjectId, ref: 'Show' },
}
)
module.exports = mongoose.model('Trailer', trailerSchema)
const mongoose = require('mongoose')
const Schema = mongoose.Schema
var movieSchema = new Schema(
{
title: {
type: String,
required: true,
},
rating: {
type: Number,
},
}
)
module.exports = mongoose.model('Movie', movieSchema)
in the Trailer collection there are some documents with the movieId field and some with showId.
Now how can I fetch all the movies or shows that have trailers?
because you just stored movieId in TrailerSchema and movieSchema don't have field like TrailerId:[{type: mongoose.Schema.Types.ObjectId, ref: 'Trailer'}], can not use populate...
but for your issue at first
let listOfIds = await Link.find( { movieId: { $exists: true } }, 'movieId._id' ).lean()
I don't know real data stored in Trailer collection for query in Trailer.find after get IDs you should search in Movie collection to get all info
let listOfMovies = await Movie.find({ _id: { $in: listOfIds.map((id) => {if(id.movieId) return id.movieId._id} ) }, })
I am trying to use populate(), however it seems like it doesn't contain transactions in user.
Is there something wrong in my code?
The transaction Table contains userId. Therefore, I thought it would automatically contains array of transactions that matches with the userId.
User Table
Transaction Table
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema(
{
name:
{
type: String,
required: true
},
transactions: [
{
type: Schema.Types.ObjectId,
ref: 'Transaction'
}
],
},
{
timestamps: true
}
);
module.exports = mongoose.model('User', userSchema)
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const transactionSchema = new Schema(
{
userId:
{
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
payer: String,
points:
{
type: Number,
reqruied: true
}
},
{
timestamps: true
}
)
module.exports = mongoose.model('Transaction', transactionSchema)
exports.getUsers = async (req, res, next) => {
User
.find()
//.findOne({ _id: "6009f3d8019a22479cb21a5d"})
.populate('Transaction')
.then(user => {
console.log(user)
})
}
In your User-Schema you've defined the transactions as transactions, so you need to populate it under this name:
User.find()
.populate('transactions')
.then(user => {
console.log(user)
})
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')
}
});
I have already checked the other entries on StackOverflow, but it did not help.
I am building a RESTapi with node.js, and I am using MongoDB with mongoose
I have a Schema that contains three different models. I am able to save POST request to the entry. I am sure that entry is saved because I checked on atlas.mongo. However, I have a problem when I am trying to use GET request.
It gives this error:
Cast to ObjectId failed for value "" at path "_id" for model
These are my Models: (These models are in different files)
const Model1 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
word1: { type: [String], require: true }
});
----------------------------------------------
const Model2 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
word2: { type: [String], require: true }
});
----------------------------------------------
const Model3 = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
element1: { type: [String], default: ""},
element2: { type: [String], default: ""}
});
----------------------------------------------
const Word = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
md3: { type: mongoose.Schema.Types.Mixed, ref: 'Model3', require: true },
md2: { type: mongoose.Schema.Types.Mixed, ref: 'Model2', require: true },
md1: { type: mongoose.Schema.Types.Mixed, ref: 'Model1', require: true }
});
This is my POST request:
exports.entry_create = (req, res, next) => {
const newModel3 = new Model3({
_id: new mongoose.Types.ObjectId(),
element1: req.body.element1,
element2: req.body.element2
});
const newModel2 = new Model2({
_id: new mongoose.Types.ObjectId(),
word2: req.body.word2
});
const newModel1 = new Model1({
_id: new mongoose.Types.ObjectId(),
word1: req.body.word1
});
const newEntry = new Word({
_id: new mongoose.Types.ObjectId(),
md3: newModel3,
md2: newModel2,
md1: newModel1
});
newEntry
.save(); // i have also then() and catch() part
};
This is where I got the error on Postman
exports.entry_get_all = (req, res, next) => {
Word.find()
.select('_id md3 md2 md1')
.populate('md3')
.populate('md2')
.populate('md1')
.exec()
.then(docs => {
res.status(200).json({
numOfEntries: docs.length,
Entries: docs.map(doc => {
return {
_id: doc._id,
md3: doc.md3,
md2: doc.md2,
md1: doc.md1,
request: { type: 'GET' }
}
})
});
}); // i have also catch() part
};
What could be the problem? Is _id's of md3, md2 & md1 returns null?
I believe it has to do with your references md1, md2 and md3. The way you reference another model is by the _id, which in your case it's and ObjectId. That being said, when you define md1, md2, and md3 you say the type is mixed, not an ObjectId. Do this instead:
const Word = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
md3: { type: mongoose.Schema.Types.ObjectId, ref: 'Model3', require: true },
md2: { type: mongoose.Schema.Types.ObjectId, ref: 'Model2', require: true },
md1: { type: mongoose.Schema.Types.ObjectId, ref: 'Model1', require: true }
});
Also note: You don't need to explicitly create a new ObjectId when creating an instance of your model. If using mongoose, it creates the _id for you! So you can just create a new Word like this:
let md1 = null;
let md2 = null;
let md3 = null;
const newModel3 = new Model3({
element1: req.body.element1,
element2: req.body.element2
});
// Save newModel3
newModel3.save()
.then((_md3) => {
md3 = _md3;
const newModel2 = new Model2({
word2: req.body.word2
});
return newModel2.save();
})
.then((_md2) => {
md2 = _md2;
const newModel1 = new Model1({
word1: req.body.word1
});
return newModel1.save();
})
.then((_md1) => {
md1 = _md1
const newEntry = new Word({
md3: md3._id,
md2: md2._id,
md1: md1._id
});
return newEntry.save();
})