Pushing into array mongoose and mongo - mongodb

I get the following error Cannot create field 'likes' in element whenever I am trying to push into my likeList array nested inside my comments.
When executing the following:
Feed.findOneAndUpdate(
{
owner: req.body.authorId,
"posts.comments.commentList._id": req.body.commentId
},
{
$push: {
"posts.$.comments.commentList.likes.likeList": {
user: req.user._id,
avatar: req.user.profile.profile_picture.url,
name: req.user.name
}
)
And my schema is as follows:
Feed Schema
owner: {
type: Schema.Types.ObjectId,
ref: "userType"
},
posts: [
{
author: {
userType: {
type: String,
enum: ["IndustryPartner", "User", "School"]
},
user: {
type: Schema.Types.ObjectId,
ref: "posts.author.userType", //<- This may cause an issue, if there are any issues with retrieving user fields, CHECK THIS
required: true
},
name: { type: String, required: true },
avatar: { type: String, required: true }
},
comments: {
totalComments: { type: Number, default: 0 },
commentList: [
{
likes: {
totalLikes: { type: Number, default: 0 },
likeList: [ <---//Trying to push here
{
user: { type: Schema.Types.ObjectId, ref: "User" },
avatar: { type: String },
name: { type: String },
date: {
type: Date,
default: Date.now
}
}
]
...
I am not sure if it's an issue with the query I am using in the first parameter to filter.
Update entire error message
It is odd because it appears that it is actually finding the correct commentList to go to, but is unable to access the likes field within the array itself. Am I wrong assuming that this should be able to step through it? posts.$.comments.commentList.likes.likeList
{ MongoError: Cannot create field 'likes' in element {commentList: [ { likes: { totalLikes: 0, likeList: [] },
_id: ObjectId('5cf6b3293b61fe06f48794e3'), user: ObjectId('5c9bf6eb1da18b038ca660b8'), avatar: "https://sli.blob.core.windows.net/stuli/
profile-picture-e1367a7a-41c2-4ab4-9cb5-621d2008260f.jpg", name: "Luke Skywalker", text: "Test comment from Luke", repliesToComment: [], date: new Date(1559671593009) } ]}

After further research, it appears the positional operator is no longer useful after stepping through 2 levels of arrays. So, the solution would be to use JS to change push the values into the array and then save them.

Related

update a nested document reference [duplicate]

This question already has answers here:
Updating a Nested Array with MongoDB
(2 answers)
MongooseJS - How to save document and referenced document
(2 answers)
Closed 3 years ago.
I have a document called MentorProfile that has a reference to document CommentFeed. I am executing the following:
MentorProfile.findOneAndUpdate(
{
_id: req.body.profileId,
'lessons._id': req.body.lessonId,
'lessons.completedList.userData': { $ne: req.user._id }
},
{
$push: {
'lessons.$.completedList': {
name: req.user.name,
avatar: req.body.userAvatar,
userRecord: req.user._id
}
},
$push: {
'lessons.$.commentFeed.comments': {
user:{name:'name', avatar:'avatar', userRecord:'8u38u3jfj'}
text: 'test'
}
}
},
{ new: true }
)
I am wanting to push a new comment to the comments array, where the array is nested as follows:
MentorProfile>CommentFeed>comments
The code snippet I attached doesn't work, i'm sure i'm missing something obvious
MentorProfile snippet of relevant info
lessons: [
{
completedList: [
{
name: { type: String, required: true },
avatar: { type: String, required: true },
userData: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}
],
stepType: { type: String, required: true },
commentFeed: { type: Schema.Types.ObjectId, ref: 'CommentFeed', required: true }
}
]
CommentFeed snippet
comments: [
{
user: {
name: { type: String, required: true },
avatar: { type: String, required: true },
userRecord: {
type: Schema.Types.ObjectId,
ref: 'User'
}
},
text: { type: String, required: true }]}

Associate one schema with another

I have my user schema:
const userSchema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
date: { type: Date, default: Date.now },
active: { type: Boolean, default: false }
});
I want to create a leave status schema. Data will be given by only one user about all leave status. I want to associate each one of the leave status to there respective user schema id. I tried leave status schema as the following:
const leaveSchema = new Schema({
leave: [
{
email: { type: String, required: true },
month: { type: String, required: true },
year: { type: Number, required: true },
earnedleave: { type: Number },
sickleave: { type: Number },
festivalleave: { type: Number },
compoff: { type: Number }
}
]
});
How can i associate my emailid with userschema. Can it be possible? If so, how can i tweak it?
We don't need to associate the schema to get leave based on user, You can use aggregation for that,
db.user.aggregate([
...
{$lookup: {from: "leave", localField: "email", foreignField: "leave.email", as: "leaves"}},
...
]);
Still, If you like to associate two collection, You have to use ref using ObjectId
const leaveSchema = new Schema({
leave: [
{
user: { type: Schema.Types.ObjectId, ref: 'user' }, //Your model name as reference
email: { type: String, required: true },
month: { type: String, required: true },
year: { type: Number, required: true },
earnedleave: { type: Number },
sickleave: { type: Number },
festivalleave: { type: Number },
compoff: { type: Number }
}
]
});

Ordering two reference arrays together

Suppose I have the following schemas:
var QuizSchema = new mongoose.Schema({
name: { type: String, required: true },
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }],
questionGroups: [{ type: mongoose.Schema.Types.ObjectId, ref: 'QuestionGroup' }]
});
var QuestionSchema = new mongoose.Schema({
number: { type: String, required: true }, // e.g. 1, a, i, anything
question: { type: String, required: true },
type: { type: String, enum: ['multiple choice', 'multiple select', 'short answer'] },
choices: [String],
answers: [String]
});
var QuestionGroupSchema = new mongoose.Schema({
number: { type: String, required: true }, // e.g. 1, a, i, anything
prompt: { type: String },
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }]
});
I am trying to design a way that will allow me to order questions and question groups together.
I was thinking maybe of adding a new field order
var QuizSchema = new mongoose.Schema({
// ...
order: [
{
type: { type: String, enum: ['Question', 'QuestionGroup'] },
id: mongoose.Schema.Types.ObjectId // reference
}
]
});
such that in the database, the field would contain something such as
[
{ type: 'Question', id: ObjectId('57867a34567g67790') },
{ type: 'Question', id: ObjectId('57867a34567g67765') },
{ type: 'QuestionGroup', id: ObjectId('69864b64765y45645') },
{ type: 'Question', id: ObjectId('57867a34567g67770') },
{ type: 'QuestionGroup', id: ObjectId('69864b64767y45647') }
]
This may mean that I would need to "populate" the ordered list of questions and question groups as
quiz.populate('questions questionGroups').exec(function (err, quiz) {
// sort questions and groups by the order
quiz.order = quiz.order.map(function (o) {
if (o.type === 'QuestionGroup') {
return quiz.questionGroups.id(o.id);
}
return quiz.questions.id(o.id);
});
});
So my question: is there a better way to design this?
Virtuals can come in handy here; without persisting order field in db and doing calculations on client each time:
var QuizSchema = new mongoose.Schema({
name: { type: String, required: true },
questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }],
questionGroups: [{ type: mongoose.Schema.Types.ObjectId, ref: 'QuestionGroup' }]
},
{
toObject: {
virtuals: true
},
toJSON: {
virtuals: true
}
}
);
QuizSchema
.virtual('order')
.get(function() {
return this.questions.concat(this.questionGroups); //questions followed by questionGroups
});
Sort on createdAt is of course optional, but for that you need to have this field in Question and QuestionGroup:
Quiz.find({}, function (err, quiz) {
//...
})
.populate({path : 'questions', options: {sort: { 'createdAt': 1 }}})
.populate({path : 'questionGroups', options: {sort: { 'createdAt': 1 }}});

Mongoose: How to query objects inside populate? [duplicate]

This question already has answers here:
Querying after populate in Mongoose
(6 answers)
Closed 6 years ago.
I have this route for searching partial user input for orderId.
ordersAdminRouter.route('/searchorder/:term')
.get(function(req, res){
term = req.params.term;
console.log(term);
Orders.find({orderId: new RegExp(term)})
.populate({ path: 'userPurchased products.product', select: '-username -password' })
.exec(function(err, orders){
if (err) throw err;
console.log(orders);
res.json(orders);
});
});
Here is my schema
var orderSchema = new Schema({
orderId: { type: String },
userPurchased: { type: Schema.Types.ObjectId, ref: 'users' },
products: [
{
product: { type: Schema.Types.ObjectId, ref: 'products' },
size: { type: String, required: true },
quantity: { type: Number, required: true },
subTotal: { type: Number, required: true }
}
],
totalQuantity: { type: Number },
totalPrice: { type: Number },
modeOfPayment: { type: String },
shippingAd: { type: String },
refNumber: { type: String },
isDone: { type: Boolean, default: false },
orderStatus: { type: String, default: 'Pending' },
dateOrdered: { type: Date, default: Date.now() },
fromNow: { type: String }
});
Now I need to search for the firstname and lastname inside userPurchased which I only get when I populate. How can search it?
I could not understand what kind of information you are saving in the 'userPurchased' field. I assume the users are in a different collection and you're only persisting the id of the user in the userPurchased. If you are just placing the id, you can search using the following query:
orderSchema.find({userPurchased : 'id'})
If you're putting an object with fields, there's no mystery either. Just use the . operator. For example:
orderSchema.find({userPurchased.firstName : 'name'})
Hope it helped you

Syntax error Unexpected token ILLEGAL Mongo Console

I'm trying to remove a document from an array threads that is a field in the collection's head document.
In Mongodb console I write following query:
db.inboxes.update({}, { $pull: {threads: {"_id":ObjectId(”5550b41ce7c33013c8000006”)}}})
But I keep getting:
Unexpected token ILLEGAL
It's driving me crazy. The Collection's schema is as following:
var inboxSchema = mongoose.Schema({
user: {
type: mongoose.Schema.ObjectId,
ref: 'userSchema',
required: true
},
threads: [{
name: String,
guid: String,
with: {
_id: {
type: mongoose.Schema.ObjectId,
ref: 'userSchema'
},
name: {
username: String,
firstname: String,
lastname: String
},
email: {
type: String,
match: /\S+#\S+\.\S+/
}
},
messages: [{
heading: String,
sent: {
type: Date,
default: Date.now
},
from: {
type: mongoose.Schema.ObjectId,
ref: 'userSchema'
},
to: {
type: mongoose.Schema.ObjectId,
ref: 'userSchema'
},
body: String
}],
updated: {
type: Date,
default: Date.now
},
unreadMessage: Boolean
}]
});
Take a look at your query
db.inboxes.update({}, { $pull: {threads: {"_id":ObjectId(”5550b41ce7c33013c8000006”)}}})
in ObjectId argument you have wrong quote marks ” instead of ". Replace them and you will get rid of the error :)