'Small images (<4MB) in MongoDB, should I use gridFS?
Rather simple question and request here, but haven't been able to find a firm answer yet. I am new to multer, Node, and MongoDB and it's been a bigger struggle than I expected.
I want to store small JPEGs in MongoDB, probably not more 4 MB each. I understand that BSON can be up to < 16 MB, and if larger, must be handled by gridfs.
These images would just be profile photos for each _id I have in a collection. So far, I have been able to upload files locally using just multer. Now I am trying to figure out how to get these images in MongoDB and in the correct way.
Do I need gridfs for such small images? What would be my best plan to execute this?
I am picturing doing an upsert of the file to the database but wonder if this will just upload the filename and not the image itself? How would I change my "schema" to accommodate this? If you have an idea of how to change my upsert below (vs going into gridFS), that would be ideal. Here is the code.
Database update:
const updatePlace = async (place) => {
const database = await connect();
return database.collection('place').findOneAndUpdate(
{ _id: new ObjectID(place._id) },
{
$set: {
name: place.name,
category: place.category,
city: place.city,
state: place.state,
country: place.country,
image: { filename: place.image, mime: 'image/jpeg' },
},
},
{ upsert: true, returnOriginal: false }
);
};
The storage and upload:
const multer = require('multer');
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './public/uploads');
},
filename: function (req, file, cb) {
cb(null, Date.now() + '_' + file.originalname);
},
});
const upload = multer({ storage: storage });
Mongo DB item as it is now:
{
"_id": {
"$oid": "5fbc37c4fc13ae680b00001e"
},
"name": "Petronas Towers",
"category": "activity",
"city": "Kuala Lumpur",
"state": "Kuala Lumpur",
"country": "Malaysia",
"image": {
"filename": "petronas.jpg",
"mime": "image/jpeg"
}
}
Solution 1:[1]
GridFS is not a bad choice. You get:
- Automatic index creation by the driver, hence efficient retrieval
- Flexibility if your images grow beyond 16 mb
- Separate metadata and content storage
You can alternatively use the binary type and store image data directly in fields. This will have less overhead but:
- You should either still store metadata separate for content or benchmark that solution vs one where the content is inline in the documents (because skipping over content bytes can be slow when you just need metadata)
- You would need to handle metadata yourself
Solution 2:[2]
You are encouraged to save files that are small in size (less than 16 MB) to MongoDB as data of the Buffer type (i.e. BSON binary type). BSON binary type is used to store any kind of binary data. BSON binary type corresponds to the RDBMS BLOB type, and it’s the basis for two kinds of binary object storage provided by MongoDB (the other being GridFS). GridFS is a specification in MongoDB that makes possible storing large files (like videos, large audio files and images) in MongoDB by dividing a given file into several chunks, which in turn gives us the ability to fetch and load only parts of the file as required, rather than retrieving the whole file.
It is recommended that you do not use GridFS if all the files you need to store are less than 16 MB in size. If this is the case, and you still want to take advantage of using MongoDB, simply store the file directly in a normal MongoDB document. The maximum size of a BSON document is 16 MB, so if all your files are smaller, using GridFS is a waste of resources.
But for educational purposes, there is nothing wrong if you use GridFS for files smaller than 16MB, the above applies only to production level projects.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | D. SM |
Solution 2 | user36339 |