How to update document of mongodb using multiple conditions? - javascript

I have a post schema that simply has attributes like _id, text, likes and comments. I want to push user id into likes array it if fulfills two conditions. Firstly the id of the post should match the query param and then the likes array should not already contain the id of the person trying to like the post. Instead error msg should come: Post already liked.
Like key pair from post schema
likes:[{
user:{
type: Schema.Types.ObjectId,
refPath:'onModel'
}
}]
I wrote the following query but it doesn't work. The update part works fine but some issue with the first argument.
Post.update({$and: [{ _id: req.params.postid},{"likes": { $ne : { user:
authorizedData.jwt_payload.patient._id }}}]},
{ $push: { likes: {user: authorizedData.jwt_payload.patient._id }}})
.then(post => res.json(post))
.catch(err => res.json(err))
Any suggestions please?

Ok, it can be simple in this way :
Post.update({
_id: req.params.postid,
'likes.user': {
$ne:
authorizedData.jwt_payload.patient._id
}
},
{ $push: { likes: { user: authorizedData.jwt_payload.patient._id } } })
.then(post => res.json(post))
.catch(err => res.json(err))

Related

Mongoose - Deleting documents is unresponsive

I'm trying to use Mongoose (MongoDB JS library) to create a basic database, but I can't figure out how to delete the documents / items, I'm not sure what the technical term for them is.
Everything seems to work fine, when I use Item.findById(result[i].id), it returns a valid id of the item, but when I use Item.findByIdAndDelete(result[i].id), the function doesn't seem to start at all.
This is a snippet the code that I have: (Sorry in advance for bad indentation)
const testSchema = new schema({
item: {
type: String,
required: true
},
detail: {
type: String,
required: true
},
quantity: {
type: String,
required: true
}
})
const Item = mongoose.model("testitems", testSchema)
Item.find()
.then((result) => {
for (i in result) {
Item.findByIdAndDelete(result[i].id), function(err, result) {
if (err) {
console.log(err)
}
else {
console.log("Deleted " + result)
}
}
}
mongoose.connection.close()
})
.catch((err) => {
console.log(err)
})
I'm not sure what I'm doing wrong, and I haven't been able to find anything on the internet.
Any help is appreciated, thanks.
_id is a special field on MongoDB documents that by default is the type ObjectId. Mongoose creates this field for you automatically. So a sample document in your testitems collection might look like:
{
_id: ObjectId("..."),
item: "xxx",
detail: "yyy",
quantity: "zzz"
}
However, you retrieve this value with id. The reason you get a value back even though the field is called _id is because Mongoose creates a virtual getter for id:
Mongoose assigns each of your schemas an id virtual getter by default which returns the document's _id field cast to a string, or in the case of ObjectIds, its hexString. If you don't want an id getter added to your schema, you may disable it by passing this option at schema construction time.
The key takeaway is that when you get this value with id it is a string, not an ObjectId. Because the types don't match, MongoDB will not delete anything.
To make sure the values and types match, you should use result[i]._id.

Loop custom array from mongoose returned empty

here is my problem
I want to loop data from two entities Project and User, my Project entity have a field with User id called creatorId.
I looped it and tried to add my user data _id, displayname and avatarUrl.
For now that work, but when I send it from the backend to the frontend nothing appears, like the array is empty.
const projectList = [];
Project.find({}, function(err, projects) {
projects.map(project => {
User.findById(project.creatorId, function(err, creator){
projectList.push({
_id: project._id,
title: project.title,
description: project.description,
avatarUrl: project.avatarUrl,
creationDate: project.creationDate,
projectCreator: {
_id: creator._id,
displayname: creator.displayname,
avatarUrl: creator.avatarUrl
},
git: project.git
})
})
})
});
res.send(projectList);

Unable to remove item from array using Mongoose / UpdateOne

I have a Node.js application in which I am trying to remove an object from an array when an API endpoint is hit. I so far have been unable to get it to update/remove the object. Currently, the below query returns with no error but upon checking into my DB I am still seeing it. Below is my query and basic response (I will be adding more but that is outside the scope of this question). I have also included a sample of my data model.
In the below data model I am trying to remove the whole object from the foo array as it is no longer needed.
Code
const ID = req.params.id
await FooBar.updateOne({foo: {$elemMatch: {v_code: ID}}}, { $pull: {v_code: ID}}, (err) => {
if(err) return res.json({success: false, err})
return res.json({success: true, id: ID})
})
Data model
{
bar: [
{
foo: [
{
v_code: <>
_id: <>
}
]
}
]
}
I'm sure this has been asked for in other questions but none specific to my data model. I've tried piecing together multiple SO posts and that is how I got the $elemmatch and the $pull portions of my query and so far I've had zero luck
give the following command a try:
db.collection.updateOne(
{
"bar.foo.v_code": ID
},
{
$pull: { bar: { foo: { $elemMatch: { v_code: ID } } } }
}
)
https://mongoplayground.net/p/iqJki-mnHSJ

mongoose extract nested arrays from multiple objects into one array

const userSchema = new Schema(
{
_id: Schema.Types.ObjectId,
name: String,
posts: [{ type: Schema.Types.ObjectId, ref: "Post" }],
following: [{ type: Schema.Types.ObjectId, ref: "User" }]
}
};
I want to extract all the posts from all the Users in the 'following' array, put them into one single array, sort them and then display the first 20. I was wondering if that is possible within the cursor or if I have to load it into memory.
function createFeed(user) {
User.findOne({ name: user })
.populate({
path: "following",
populate: {
path: "posts"
}
})
//put all the posts into one array
.sort(...) //sort by time created
.limit(...) //only get the newest n posts
.exec((err, result) => {
if (err) console.log("error", err);
console.log("result", //sorted tweets array);
});
};
(I don't want to filter all the posts in my 'Posts' collection to check if they are made by the user since that would be a lot more expensive)
You can use distinct query in mongoDB
db.User.distinct('following',{})
If you are trying to filter your populate with a condition, then you should be doing this:
User.findOne({ name: user })
.populate({
path: 'posts',
match: { user: 'XXX' }
})
Even more better would be to query the posts with the user filter condition and then populate user details.

Mongodb/Mongoose: Filling Array of ObjectIds (references)

I have a mongodb running (MEAN environment) with two collections (users and books). One of those collections (myusers) contains an array of Objectids (references to documents of books collection) as such:
var UserSchema = new Schema({
[...],
externalids: [{type: Schema.Types.ObjectId, ref: 'Books', required: false}]
}, {collection: 'myusers'});
At runtime, I'd like to constantly fill that array (externalids) with ids of new book documents. This is how I do it:
var newBook = new Book({ ... });
newBook.save(function (err){
if (err){
//whatever
}else{
User.update({ _id: req.user._id }, { $set: { externalids: newBook._id }}, function(err){
//whatever
});
}
});
Unfortunately, I can't use something like:
externalids: externalids.push(newBook._id)
I even tried:
User.update({ _id: req.user._id }, { $push: { externalids: newBook._id }}
But it wouldn't help either.
Thus, the array always only contains one value (the latest) and won't be filled up. Is there a quick way to append more values? Would be nice if there was a quicker way than reading the array content first, storing it to a local temporary array, append the new value and write the entire array back...
Cheers
Igor
Try $addToSet instead of $push to avoid duplicate id.
User.update({ _id: req.user._id }, { $addToSet : { externalids: newBook._id }}
What can be your issue is that you previously use $set to update an user. This will initially create externalids as string, not array, hence you cannot use $push/$addToSet on externalids afterwards. To correct that, try to update your user externalids as an array first:
User.update({ _id: req.user._id }, { $set : { externalids: [] }}

Categories