Dynamic URL with mongo method - node.js

Regarding these post : Mongoose prototype : how to insert an url dynamically?
I'm looking to do pretty much the same (URI dynamically insert).
The solution provided is good but I do not understand some things...
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var PicturesSchema = new Schema({
album : { type : String, required : true, trim : true },
pictures : { type : Array, required : false, trim : true }
});
PicturesSchema.virtual('pictureUrls').get(function() {
return this.pictures.map(function(picture) {
return 'https://s3.amazonaws.com/xxxxx/'+ picture;
});
});
var Pictures = mongoose.model('Pictures', PicturesSchema);
// Demo:
var pictures = new Pictures({
album : 'album1',
pictures : [
'1434536659272.jpg',
'1434536656464.jpg',
'1434535467767.jpg'
]
});
console.log( pictures.getPics() );
The given solution injects a "virtual field" in addition to retaining the "pictures" field with the name of the images (without URL).
How to retain only the field "PicturesURL" containing the full URL of the image without displaying a redundancy with the "Pictures" field?
How to retrieve and display the JSON format query results as it knowing that data.ToJson returns an error: has no method 'toJson'?
Pictures.find().exec(function(err, data){
if(err){
console.log(err);
}
console.log('%j', data.toJSON({ virtuals : true }) );
});

A strategy to store only the picture url without the picture would be to create a Mongoose middleware on save.
You could then populate the picture field with the name of the picture, and the full url will be the one stored in the database and later retrieved.
For example:
PictureSchema.pre('save', function (next){
if (this.isModified(pictureUrls){
this.pictureUrls = this.pictureUrls.map(function(picture){
return 'https://s3.amazonaws.com/xxxxx/'+ picture;
})
}
});
With this solution, every time you modify the pictures array, it will go over every element of the array and add the s3 path.
Since it won't be a virtual, it will be easier for you to use the model with event using toObject or toJson.

Related

Update element of any particular index in an array in MongoDb using mongoose in Node.js

Hi I tried to update the element at a particular index in an array but I'm not able to update it. It is updating the entire array. Not able to figure out how to update any particular index. Also tried
{$set:{"Data.1:req.body}}
this is updating at 1st index but I don't want to hardcode the index value. It should take from frontend. Let say I have a schema in which I have Data who's type is array and default value is as shown below or anything in the same format.
Data: {
type: Array,
Default: ["0","1","0"]
}
Whenever I'll create a user then Data field will contain these default values, But now I want to update the value at any index (coming from frontend) of Data array of any user created.
I tried findByIdAndUpdate method but I don't know what to pass in set property. If I'm passing this {$set: req.body} and In postman I'm giving any value of Data then obviously it is updating Data array but I want to update value at any index which I'm passing from frontend, let say the index I'm passing is 2 then it should update the value of array at index 2, similarly I can pass any index from frontend how should I do that. What changes I have to make in {$set : } Thanks in advance.
Waiting for any help or suggestions. Thanks
It appears that you can solve this in backend logic if you are passing the index from the frontend.
You can dynamically specify the index, based on the input from the frontend, before you send a query.
const updateUserData = async (req, res) => {
const { index, user_id, new_value } = req.body;
try {
const update = {};
update[`Data.${index}`] = new_value;
const data = await Users.updateOne(
{ _id: user_id },
{ $set: update }
);
return res.status(200).json({ success: true });
} catch (error) {
return res.status(500).json({ success: false });
}
};

save images mongodb node js

schema
images:{ type : Array , "default" : [] }
controller
return new Promise(function(resolve,reject){
var dt = new Date(req.body.dateOfBirth)
var experiences = new Experiences({
'images': req.body.images
});
experiences.save(function(err,experiences){
if(err){
reject(err);
}else{
resolve(experiences);
}
});
});
I need to save more than one image into single image
posting Data as :
"https://images.pexels.com/photos/346768/pexels-photo-346768.jpeg?w=940&h=650&auto=compress&cs=tinysrgb","https://images.pexels.com/photos/287240/pexels-photo-287240.jpeg?w=940&h=650&auto=compress&cs=tinysrgb"
but when i viewing my document. getting result like this :
"images" : [
"\"https://images.pexels.com/photos/346768/pexels-photo-346768.jpeg?w=940&h=650&auto=compress&cs=tinysrgb\",\"https://images.pexels.com/photos/287240/pexels-photo-287240.jpeg?w=940&h=650&auto=compress&cs=tinysrgb\""
]
what am i doing wrong please help?
i want result like:
"images" : [
"https://images.pexels.com/photos/346768/pexels-photo-346768.jpeg?w=940&h=650&auto=compress&cs=tinysrgb","https://images.pexels.com/photos/287240/pexels-photo-287240.jpeg?w=940&h=650&auto=compress&cs=tinysrgb"
]
My guess is that req.body.images is stringified. I believe it is a string containing many values, not an array. When you post that to MongoDB, since you specified that images must be an array, it saves it as an array of strigified values.
So, blind guess, but I believe you are posting (client-side) something like :
$.post("/save", { images : JSON.stringify(imagesArray) } )
when you should just post your array as is :
$.post("/save", { images : imagesArray} )
But it's hard to know for sure, because we don't have the front-end code or even console.log(req.body.images)

MongoDB does not search for documents

but I cant find any items after ID,
Calendar.model inside is doc:
/* 1 */
{
"_id" : ObjectId("5a3425b58399c6c26cf1c848"),
"doctorID" : ObjectId("5a31392cc99fe923c0810096"),
"doctor" : "Bartłomiej Flis",
"calendar" : []
}
And in nodeJS API I am trying to find the doc using function:
router.get('/list-of-dates', (req, res)=> {
Calendar.find({ doctorID : req.query.doctorID})
.then((Calendar)=>{
console.log(Calendar)
res.send(Calendar)
})
.catch((err)=>{
console.log(err)
})
});
the value of req.query.doctorID is string -> 5a31392cc99fe923c0810096
Anyone can tell me why this function can't find any item? I think it is the fault that in the database variable doctorID is as ObjectId and in the API req.query.doctorID is a string, how to improve it in the API to work.
First, import in the beginning of the file the following:
const ObjectID = require('mongodb').ObjectId;
Then, change your search query to (i.e. wrap it into the ObjectId() function)
{ doctorID: ObjectId( req.query.doctorID ) }
What is the difference? MongoDB stores keys in ObjectId type, whereas you are trying to find something with type String. You were correct. That's why you do not get anything.
Let me know if that helps.

How to retrieve the desired field's value from a collection and store it's ID in another collection

I am using node js and mongodb. I have this this route code
router.get('/taglist', function(req, res) {
var db = req.db;
var collection = db.get('tagcollection');
collection.findOne({},{},function(e,docs){
res.render('taglist', {
"taglist" : docs
});
});
});
this is for getting all taglist from the database and the response rendering to taglist.jade which is given below-
extends layout
block content
h1.
Tag List
ul
each tag, i in taglist
li
#{tag.tagname}= tag._id
Now I want to search a tagname which is already stored in my taglist collection and want to store that ID belonging to tagname which matched and store it in another collection.
Right now my code is just finding all the tagname and printing all the tag_id in browser. I am new in web application and just started with node and MongoDB.
UPDATE
first code getting all the tagcollection data and second one is displaying all the id of each document.but this is not what I am expecting.
I am explaining what I am expecting-
let's suppose tagcollection contain 2 or more documents.
{
"_id" : ObjectId("ksjsed3cccjdkmx"),
"tagname" : "dinner"
}
{
"_id" : ObjectId("skd9a93cccb8kdn"),
"tagname" : "music"
}
and so on ...
first I want to search for music tag
if I find music tag is available in my tagcollection then it will display id of music tag and store this id in new collection(say in newtagcollection)
router.js:
router.get('/searchtag/:tag', function(req, res) {
var db = req.db;
var collection = db.collection('tagcollection');
collection.findOne({ tagname: req.params['tag'] }, function(e, result) {
res.render('searchtag', { tag: result });
});
});
searchtag.pug:
extends layout
block content
h1.
Tag Search
if tag
p= tag.tagname + ' = ' + tag._id;
else
p Tag not found!

mongoose-encryption and updating objects

I know the mongoose-encryption doc states:
update will work fine on unencrypted and unauthenticated fields, but will not work correctly if encrypted or authenticated fields are involved.
And I've observed that when I use the mongoose create method that my fields are encrypted into the _ct field. However if I then use findByIdAndUpdate to update my object I see the fields are created in plain text (as output from mongodb console via find command).
From save
> db.tenants.find().pretty()
{
"_id" : ObjectId("554b7f8e7806c204e0c7589e"),
"_ac" : BinData(0,"YdJjOUJhzDWuDE5oBU4SH33O4qM2hbotQTsF6NzDnx4hWyJfaWQiLCJfY3QiXQ=="),
"_ct" : BinData(0,"YaU4z/UY3djGCKBcgMaNIFHeNp8NJ9Woyh9ahff0hRas4WD80V80JE2B8tRLUs0Qd9B7IIzHsq6O4pYub5VKJ1PIQA+/dbStZpOH/KfvPoDC6DzR5JdoAu+feU7HyFnFCMY81RZeJF5BKJylhY1+mG4="),
"__v" : 0
}
After findByIdAndUpdate
> db.tenants.find().pretty()
{
"_id" : ObjectId("554b7f8e7806c204e0c7589e"),
"_ac" : BinData(0,"YdJjOUJhzDWuDE5oBU4SH33O4qM2hbotQTsF6NzDnx4hWyJfaWQiLCJfY3QiXQ=="),
"_ct" : BinData(0,"YaU4z/UY3djGCKBcgMaNIFHeNp8NJ9Woyh9ahff0hRas4WD80V80JE2B8tRLUs0Qd9B7IIzHsq6O4pYub5VKJ1PIQA+/dbStZpOH/KfvPoDC6DzR5JdoAu+feU7HyFnFCMY81RZeJF5BKJylhY1+mG4="),
"__v" : 0,
"userId" : ObjectId("55268f43cbfc87be221cd611"),
"social" : "123-45-6789",
"last" : "bar",
"first" : "foo"
}
Is there a recommended strategy for updating objects and maintaining the encryption with mongoose-encryption?
As you quoted, the documentation for mongoose-encryption clearly tells that it does not work for update.
https://github.com/joegoldbeck/mongoose-encryption
Mongoose update hook is little tricky as well.
What you can do potentially is model your collection in such a way that fields which needs to be encrypted are a separate collection altogether and in the paren collection just link them via ids.
Person = {
_id: <ObjectId>
name: Blah
..
..
documents: [
{ 'doc_id': <ObjectId1> },
{ 'doc_id': <ObjectId2> },
]
}
Documents = [
{
"_id" : <ObjectId1>,
"_ac" : BinData(0,"YdJjOUJhzDWuDE5oBU4SH33O4qM2hbotQTsF6NzDnx4hWyJfaWQiLCJfY3QiXQ=="),
"_ct" : BinData(0,"YaU4z/UY3djGCKBcgMaNIFHeNp8NJ9Woyh9ahff0hRas4WD80V80JE2B8tRLUs0Qd9B7IIzHsq6O4pYub5VKJ1PIQA+/dbStZpOH/KfvPoDC6DzR5JdoAu+feU7HyFnFCMY81RZeJF5BKJylhY1+mG4="),
"__v" : 0
}
...
...
]
This will increase code reuse as well.
I have implemented an strategy that i don´t think it is most efficient but it works.
I need to have all my data in database encrypted so i can´t use the above approach.
What i did is to create an update function that finds the document i want to modify, then i construct a new schema object and assing the _id of the found document to the new object.
Then i delete the original document and after that save the new object wich has the original _id. The only problem i found is that mongoose throw an error because duplicated _id that is printed in the console but it still works and _id aren´t duplicated.
I have tried replacing the_id and traking the document with another property but it still throw that error, anyway data is stored as expected.
exports.update= (req, res, next) => {
Solucion.findOne({_id: req.params.id})
.then(document => {
if (!document) {
res.status(404).json({
message: notFoundMessage,
data: null,
error: null
})
} else {
const solucion = new Solucion({
_id: document._id,
identificacion: document.identificacion,
informacion: document.informacion,
estado: req.body
})
Solucion.deleteOne({_id: document._id})
.then(() => {return solucion.save()})
.then(result=> {
return res.status(201).json({
message: editedSavedMessage,
data: result,
error: null
});
})
.catch(err => {
errorHandler.errorHandler(err, res);
})
}
})
};
UPDATE 29/07/2020
I have found that if you use the save method using the same _id, data is stored encrypted but Mongo creates your schema structure but with all values set to null.
Beyond that it seems to work as expected as data is not visible in DB.

Resources