Mongodb Deep Embedded Object Array Query - node.js

Hi I am facing a problem in updating an embedded object array using mongoose!
Here is the Schema:
var event = {
eTime : [String]
};
var schedule = {
events: [event]
};
var group = {
gName: {type:String},
sDate: { type: Date, default: Date.now },
schedules: [schedule]
};
MainSchema {
id : String,
groups : [group]
};
The thing which I want to do is that to update the array of eTime in events with an object of schedules. I am using this query
db.demoDb.update({
'id': 'MongoDb',
'groups':{
$elemMatch:{
'gName':'noSql'
}
}
},
{
$push:{
'groups':{
'schedules':{
'events':{
'eTime':'01-Marach-15'
}
}
}
}
}
)
but the schedules->events->eventTime is not updating with a value!!!
What wrong I am doing here?
My Main Scenario is to find the id(MongoDB) with associated gName and then update its schedules array of it.
My find query is working great but can not update the schedules... and events can be many

If I'm reading your schema correctly, the core part is an array containing an array containing an array containing an array of strings. I think you would do much better "inverting" the schema so each document represents an event. Metadata grouping multiple events can be duplicated into each event document. An example:
{
"event" : "cookie bake-off",
"gName" : "baking",
"sDate" : ISODate("2015-03-02T21:46:11.842Z")
}
The update that you are struggling with translates into an insertion of a new event document in the collection.

Related

Using updateOne with Arrays in Mongoose with NodeJS

Im working on an API for a custom game and i need to update specific fields in an array in my Database Entry. How do i do that without adding a new thing to the array, instead just updating for example the content of entry 5 in the array
Hello I'm not sure the name of your schema so I'm assuming its called Game so here is an example for how to update an index in an array assuming its the board array field you're trying to update. Also reference here for more details on updating an array field by it's index:
var fieldPosition = "board." + req.params.field
await Game.updateOne({
_id: 1
}, [{
$set: {
tempBoard: fieldPosition
}
},
{
$set: {
"$tempBoard": session.turn
}
},
{
$unset: ["tempBoard"]
}
])

Node Js and Moongoose: How to loop into array of objects and delete a particular object and then update the whole document

My document schema is as follows:
const CollectionSchema = mongoose.Schema({
ImageCategory:{type:String,required:true},
imgDetails: [
{
_id: false,
imageUrl:{type:String},
imageName:{type:String},
imageMimeType:{type:String},
}
],
Date: {
type: String,
default: `${year}-${month}-${day}`,
},
},{timestamps: true,})
So in the database for example one document has multiple images with a single image category. What I am trying to do is I want to delete an object from imgDetails array.
Let me explain my question more precisely: imgDetails is an array
Explanation: I want to loop in imgDetails and then find (where imgageUrl === req.body.imageUrl) if its match delete that whole object which have that req.body.imageUrl and then update the document.
Please guide me on how to write such a query. Regards
Demo - https://mongoplayground.net/p/qpl7lXbKAZE
Use $pull
The $pull operator removes from an existing array all instances of a value or values that match a specified condition.
db.collection.update(
{},
{ $pull: { "imgDetails": { imageUrl: "xyz" } } }
)

String + autoincrement number on mongoose

I want to create a String + number every time a value is inserted on database (the number must be autoincrement).
Is it possible to do in Schema? Or do I need to do that before the value's inserted on database?
'question' -> String followed by an autoincrement number
var random = [{
question: 'question1'
},{
question: 'question2'
},{
question: 'question3'
},{
question: 'question4'
}];
const RandomSchema = new Schema({
question: {
type: String,
unique: true
}
})
Autoincrement fields in Mongodb, don't work exactly the same way that they do in an RDBMS. There is a lot more overhead involved. Never the less, creating an auto field is a solved problem. There is also a third party mongoose-autoincrement package that make it a lot easier.
Extending, from that. Your problem is a solved problem too. Because
the string part will always be the same
Simply use string concatenation to prepend 'question' to the auto increment field at display time.
Here is what I implemented with one of the approaches #e4c5 pointed out, without the use of a third-party package.
Define add.js as below:
db.counters.insert(
{
_id: "itemid",
seq: 0
}
)
function getNextSequence(id) {
var ret = db.counters.findAndModify(
{
query: { _id: id },
update: { $inc: { seq: 1 } },
new: true
}
);
return ret.seq;
}
db.randoms.insert(
{
question: "question"+getNextSequence("itemid"),
}
)
db.randoms.insert(
{
question: "question"+getNextSequence("itemid"),
}
)
After starting a mongod instance, do mongo < add.js.

Mongoose update sub document if exists

I have following model :
var VoteSchema = new Schema({
up : Boolean
, createdBy:{type:ObjectId, ref:'users'}
, createdOn : {type:Date, default:Date.now}
});
var QuestionSchema = newSchema({
title:String
, description:String
, votes : [VoteSchema]
, createdBy:{type:ObjectId, ref:'users'}
, createdOn : {type:Date, default:Date.now}
});
var Question = mongoose.model('questions',QuestionSchema);
Suppose user1 is logged in user and question1 is current / viewing question.The user can upvote({up:true}) or downvote({up:false}) a question at any time. How can I add a new vote if a user1 have not casted a vote for question1 else update the vote.
I have been able to write the following lines of code:
QuestionSchema.statics.castVote = function(questionId, vote) {
//NOTE : vote.createdBy equalsto loggedInUserID
Q.nbind(Question.findOne, Question)({
$and:[
{_id:questionId},
{'votes.createdBy':vote.createdBy}
]
}).then(function(doc) {
if(doc) {
//I am clue less
//doc.votes is a list of votes for this question
// how can I get the particular vote casted by the user - vote.createdBy
}else {
//Question.votes.push(vote);
}
});
});
So you're part of the way there, but of course when you don't find a doc then you will not have a doc to work with in the callback. MongoDB has native ways of handling these sorts of updates, but of course you do need to test for the match as you are.
What we can do here is just work within the true or false condition of where the document exists.
Considering vote.value to be your true or false for the "upvote"
Where you do find that there is a matching document you can issue an update like this:
Question.update(
{
_id: questionId,
"votes.createdBy" vote.createdBy,
"votes.up": {"$ne": vote.value }
},
{ $set: { "votes.$.up": vote.value } }
);
So that matches and uses a positional $ operator to make sure the correct index of the matching item is updated. What I added there makes sure that you don't even touch the document where the vote.vaule is already of the same value.
And in the false condition you want to $push onto the array with the new item:
Question.update(
{
_id: questionId
},
{
$push: {
"votes": {
"up": vote.value,
"createdBy": vote.createdBy
}
}
}
);
Of course add the callback details where writeConcern is applied, which you probably do.

In Mongoose, how to filter an array of objects

I have the following schema:
var sampleSchema = new Schema({
name: String,
dates: [{
date: Date,
duration: Number
}]
});
I'd need to filters the records according to the following rule: if one of dates is later than a given date date_begin, keep the record, otherwise, don't.
I have the impression that $gte or $lte are the function I need, but I can't find a way to use them correctly. I tried
sampleSchema.find({date_begin: {$gte: 'date'}});
or some variants of that, but I can't seem to be able to make it work. Anyone has an idea of how I am supposed to do this?
To do querying on elements inside arrays, $elemMatch is used :
SampleModel.find( { dates : { $elemMatch: { date : { $gte: 'DATE_VALUE' } } } } )
If you're using a single query condition, you can directly filter:
SampleModel.find( { 'dates.date': { $gte: 'DATE_VALUE' } } )

Resources