I am using MongoDB and I am trying to grab a specific object based on its _id and all of the sibling elements as well. For example my array looks like this:
"blogs": [
{
"body": "default valuee",
"header": "another first",
"_id": "1234"
},
{
"body": "second default value",
"header": "second",
"_id": "5678"
}
]
And I am trying to grab the values that are beside the _id of 1234 (so the body,header and _id fields of just that object). I have tried a few Mongo queries but with no such luck. Any help would be great, cheers
My function is :
module.exports = function findBlog(db, id, callback){
var UserCollection = db.collection('users') //connect to business collection
UserCollection.findOne({ 'blogs._id': id }, {body: 1, header: 1, _id: { $elemMatch: { _id: id}}},function (err, user) {
if (err){
return callback({response: "3"})
}else if(!user){
return callback({response: "4"})
}else {
return callback({response: "2",data:user.blogs})
}
});
}
You should use something like this,
If you want all fields from blogs and user you can directly use,
UserCollection.find({ 'blogs._id': id }, { blogs:{ $elemMatch:{ _id: id }}},function (err, user) {
if (err){
return callback({response: "3"})
}else if(!user){
return callback({response: "4"})
}else {
return callback({response: "2",data:user.blogs})
}
});
}
If you need specific fields:
First parameter you will add condition: { 'blogs._id': id }
Second parameter you will add fields required: { "blogs.body": 1,"blogs.header": 1 }
UserCollection.findOne({ 'blogs._id': id }, { "blogs.body": 1,"blogs.header": 1 },function (err, user) {
if (err){
return callback({response: "3"})
}else if(!user){
return callback({response: "4"})
}else {
return callback({response: "2",data:user})
}
});
}
As I stated in a comment on the OP's question, the best way to to work this out is to create a Blog collection. You can then query this collection directly instead of querying the User collection.
You can still have the blogs property in the User model by linking a blog to a user. (see the Mongoose documentation on populate)
Related
I am trying to check if a document exists in MongoDB and then based on that either update the document or create a new one. However only the if statement is being recorded. I have checked that the value of documentExists is null if no document is in mongo.
router.post("/mongo", async function (req, res) {
const documentExists = await Files.findOne({
_id: req.body.id,
});
if (documentExists) {
try {
Files.updateOne(
{ _id: documentExist._id },
{ flag: req.body.flag },
function (err, result) {
if (err) {
res.send(err);
} else {
res.send(result);
}
}
);
} catch (err) {
res.status(400).send(err);
}
} else {
CREATE NEW DOCUMENT
}
})
In your case you can use findOneAndUpdate to update if there is any existing document in the collection, if there is no matching document the query returns null.
I have the following document structure:
And am trying to figure out how to delete a single object from the 'saved array', using the id in the object to select it (eg id 4182 will delete the object and all its properties at index 0). This was my attempt but not sure how to target it properly (No errors, but nothing updated):
let id = req.query.clicked_id;
console.log("\deleteSaved id:", id);
db.collection("users").updateOne(
{ username: config.username },
{ $unset: { id: id} },
(err, data) => {
if (err) {
console.log(err);
}
console.log("Item deleted from DB: ", id, data.result.nModified);
res.redirect("/saved");
}) ;
Thanks
you can find the answer very clear in the (MongoDB, remove object from array)
and my answer is
you can use $pull operator in mongodb documentation
to pull element from array
you can use this query
let id = req.query.clicked_id;
console.log("\deleteSaved id:", id);
db.collection("users").updateOne(
{ username: config.username },
{ $pull: {saved: { id: id } },
(err, data) => {
if (err) {
console.log(err);
}
console.log("Item deleted from DB: ", id, data.result.nModified);
res.redirect("/saved");
}) ;
this one will work fine
I am trying to update the favourite stations array in my database, however I just can't seem to be able to update it? I have searched for ages to try and find a solution, but nothing seems to work.
I have the ID saved in the cookie, and am sending that in the body when the update request is made...
"selected" is an array of objects. this is what will need replace the contents of the to the favouriteStations property, or add it if it is empty.
the database structure is like this:
"id": id,
"email: "test#test",
"password": "test",
"userInfo": {
"firstName": "test",
"lastName": "test",
"favouriteStations": [{array i want to replace}]
}
i have tried many different combinations, however this is what i have so far, and it doesnt work
app.post("/api/update", (req, res) => {
console.log("updating user details");
const { id, selected } = req.body;
UserModel.findOneAndUpdate(
{ _id: id },
{ userInfo: { favouriteStations: { $set: selected } } },
{ useFindAndModify: false }
)
.then((user, err) => {
if (err) {
console.log("an error?");
res.status(500).json({
error: "Server error",
});
} else if (!user) {
console.log("user not exists?");
res.status(401).json({
error: "Incorrect credentials",
});
} else {
console.log("updated?");
console.log(user);
}
})
.catch((err) => {
console.log(err);
});
});
It is unclear as to what you mean by ".. it doesn't work", can you elaborate please i.e. what errors do you receive? If none, what does happen?
The $set operator should be used in the following form, from MongoDB docs:
{ $set: { <field1>: <value1>, ... } }
In saying that, you may not be accessing favouriteStations correctly, use dot-notation to access the subdocument as follows:
...
UserModel.findOneAndUpdate(
{ _id: id },
{ $set: {'userInfo.favouriteStations': selected} } ,
{ useFindAndModify: false }
)
...
I want to query a user by id, and then bring only the the foods that match to a type, how can i do this?
var type = 'fish';
var id = '597a348286ffe50d882a3033';
User.findById(id, { 'food.type': type }, 'food', function(err, model) {
if (err) {
console.log(err);
}
if (!model) {
console.log('no model');
}
if (model) {
console.log(model);
}
});
I would use aggregate combined with $filter:
User.aggregate([{
$match: { '_id': ObjectId('597a348286ffe50d882a3033') }
}, {
$project:
{
food: {
$filter: {
input: '$food',
as: 'food',
cond: {
$eq: ['$$food.type', type]
}
}
}
}
}])
This will first select the document matching the given Id then will return the list of foods of the given type.
Just filter the food after you get the user.
User.findById(id, function (err, user) {
if (err) {
console.log(err);
}
if (!user) {
console.log('no user');
}
if (user) {
var food = user.food.filter(function (food) { return food.type === type; });
}
});
You can create an obj something like this
var obj =
{
_id:'597a348286ffe50d882a3033',
'food.type' : 'fish'
}
and then pass this function as filter
User.find(obj, function(err, model) {
if (err) {
console.log(err);
}
// find will return empty array and not null
if (!model.length) {
console.log('no model');
}
if (model) {
console.log(model);
}
});
If you are finding the object using mongo _id field you don't have to use additional filter function after query execution you directly specify in the search query
Model.findOne({_id: '123jasdoisd123', 'food.type': type },
function(err, food){
if(err) return err;
if(!food){
// send the empty data
return []
}
return food;
}
)
I have this code which searches for documents based on two ids.
User.find({
$or: [
{ id: req.body.myId },
{ id: req.body.id }
]
}, function(err, users) {
console.log(users)
});
This works fine, however, let's assume req.body.myId is undefined, then it would grab all documents that match req.body.id only. I need it to be such that if it can't be find any documents relating to one id, then it shouldn't grab anything for the other Id, giving back an empty array of users.
Make a check before executing the query and don't execute it if one of the parameters are undefined, so you don't make unnecessary calls to MongoDB. Something like:
if (!req.body.myId || !req.body.id) {
// return here empty array or whatever
}
By the way in your case usually the $in operator is used:
User.find({
id: {
$in: [req.body.myId, req.body.id]
}
}, function(err, users) {
console.log(users)
});
This is a strange requirement but ok:
function findByTwoIds(id1, id2, callback) {
if (!id1 || !id2) {
callback(null, []);
} else {
User.find({
$or: [
{ id: id1 },
{ id: id2 }
]
}, callback);
}
}
and use it with:
findByTwoIds(req.body.myId, req.body.id, function (err, users) {
if (err) {
console.log('Error:', err);
} else {
console.log(users);
}
});