Auto insert non existing value with findOneAndUpdate and upsert - mongodb

My use case :
=> UPDATE : set the current date if I found a specific email (working)
=> INSERT : a specific email with date to null if the email passed in the request is not found (not working)
I thought upsert were supposed to insert if the specific email was not found, but for some reason, it's not.
JSON Structure
"listener": [
{
"email": "email",
"date": "2019-06-23T00:22:52.190Z"
}
],
Route
exports.add_listener = function (req, res) {
Playlist.findOneAndUpdate(
{"platform.strauss": req.body.url},
{$set: {"listener.$[elem].date": new Date()}},
{
arrayFilters: [{"elem.email": req.body.email}],
upsert:true,
new:true,
}, function (err, data) {
err ? console.error(err) : res.status(200).send(data);
}
)
};

Related

MongoDB - Add / update to list of objects on document

I have a user collection, and each user has a list of products. I need to update a product using it's ID or add the product if it doesn't exist.
How can I update the product by it's id?
User Collection:
{
"_id": {
"$oid": "5fc06554266266edf5643231"
},
"products": [
{
"id": 123,
"name": "test product"
}
]
}
Using the following code I'm able to add the product, but can't update the product by it's ID.
db.users.updateOne({_id: ObjectId('5fc06554266266edf5643231')}, {
'$addToSet': {
'products': {
'id': 123,
'name': 'foobar'
}
}
}, {upsert:true})
Well, i will recommend to you to re-think your schema.
Maybe you need to create a collection called Products and in the user collection put all the id's of the products on a field called product. Then you can create a query with a populate function. Something like this
const user = await User.find(query, options)
.then(async (result) => result)
.catch((err) => logger.info(err));
const populateProducts = await Products.populate(user, populateProductsOptions)
.then(async (data) => data)
.catch((err) => logger.info(err));
But if you don't want to modify your schema you have to do several querys. There is no way to do this in single query. You have to search the document first:
If document exist:
db.users.updateOne( {_id: 123456 , yourQueryProduct ,
false ,
true);
db.users.updateOne( {_id: 123456: 123456 } ,
{$pull: {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
false ,
true);
db.users.updateOne( {_id: 123456: 123456 } ,
{$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } ,
false ,
true);
else if document don't exist you can addToSet directly
The issue is that on this line: db.users.updateOne({_id: "5fc06554266266edf5643231"}
The _id field is being interpreted as a String, but the document you want to update saves its _id as an ObjectId. All you have to do it make it an ObjectId is this:
db.users.updateOne({_id: ObjectId("5fc06554266266edf5643231")}, {
'$addToSet': {
'products': {
'id': 123,
'name': 'foobar'
}
}
}, {upsert:true})

can't update DB using put request in express.js

I'm trying to update the languages_known through post request to the mongodb collection using the body of the request but its not updating i'm newbie any help would be really appreciated.
mongodb document :
{
"_id": {
"$oid": "5d63e81c342987154cdc698e"
},
"name": "anjana",
"email": "anju#gmail.com",
"age": "22",
"languages_known": [
"Bengali",
"Kannada"
],
"phone": "684684684846"
}
server code :
app.put('/students/add',function(req,res){
var myobj={
$set:{_id:require('mongodb').ObjectID(req.body.id),languages_known:req.body.remove}
}
db.collection('students').updateOne({languages_known:req.body.add},myobj,function(err,result){
if(err){throw err}
console.log("updated")
})
})
request body :
{
"id":"5d63e81c342987154cdc698e",
"remove": ["Bengali", "Kannada"],
"add": ["Tamil", "Punjabi"]
}
I've expected to update the languages_known field using this req through postman to this id
Ok this issue is with the query, you can't update _id of a document like that, also as your requirement is not to do that, Please try this :
server code :
// replace languages_known with new languages based on _id, in case if you wanted to update the array you can use $push
app.put('/students/add', function (req, res) {
const id = require('mongodb').ObjectID(req.body.id)
let updateQuery = {
$set: { languages_known: req.body.add }
}
db.collection('students').updateOne({ _id: id }, updateQuery, function (err, result) {
if (err) { throw err }
console.log("updated")
})
})

mongooseJS returning an object after update?

Is it possible to return a document after updating it?
my current code looks something like this:
module.exports.updateEmail = function(id, data, callback) {
User.findByIdAndUpdate( id, {
$set: { "email": email }
}, callback);
}
how would I pull the User document and pass it back?
add {new : true} update option, to return the updated document, the callback will have the updated document you can return it
module.exports.updateEmail = function(id, data, callback) {
User.findByIdAndUpdate( id,
{$set: { "email": email }},
{new : true}, // to return updated document
callback
);
}

Insert user defined time point in Mongodb

I want to use some specified time points in my data. I have used new Date('Dec 26, 2014') to insert a specified date. Is there any way to insert some different time points in a particular day in Mongodb?
Consider session information in a social network. Let my document is like below: { "name" : "koushik", "login_time" : "a new time", "logout_time" : "a new time"}. I want to explicitly mention "a new time" in mongo shell.
According to your comment, you have, in MongoShell, to use ISODate object:
test> db.test.insert({new_date: ISODate("1977-05-25")})
test> db.test.find()
{
"_id": ObjectId("5682590a09833d813d33dd0c"),
"new_date": ISODate("1977-05-25T00:00:00Z")
}
Use update for maintaining login/logout info in session for your application.
db.socialnetworksession
.find({'name':'koushik'})
.update(
{ $set: {'login_time': new Date(), 'logout_time': new Date()} },
function (err, result) {
if (err) {
cb( err, null );
}
cb( null, result );
});

How to get string value inside a Mongodb document?

I have this document stored in mongodb document:
{
"_id":ObjectId("4eb7642ba899edcc31000001")
"hash":"abcd123"
"value":"some_text_here"
}
I am using NodeJS to access the database:
collection.findOne({'hash' : req.param('query') },
function(err, result){
console.log(res);
});
The result of this query is the whole document, however I need to get only the "value" text: "some_text_here"
How can this be done?
You can specify the fields that you are interested in (_id will always be returned, though):
collection.findOne({'hash': req.param('query') },
{fields: ['value'] },
callbackFunction );
You can do it such way:
collection.findOne({'hash' : req.param('query') },
function(err, result){
console.log(result.value);
});