从 MongoDB 检索图像的最佳方法是什么?
what is the best approach to retrieve images from MongoDB?
我有一个 Web 应用程序,它使用 GridFS 从 MongoDB 存储和检索图像。我的问题是,当用户发出提示服务器从数据库中检索图像的请求时,需要很长时间。
例如,仅检索数据库中的两个文档然后遍历每个文档以获取与每个文档关联的图像的请求最多可能需要 45 秒。在这种情况下,从数据库中检索到的图像总量约为 10。
这是我的方法:
// 1. Query the database
var users = await User.find({ 'key’': value });
// 5. Use GridFs to get the image and return the result
const createStream = (filename) => {
return new Promise((resolve, reject) => {
let readstream = gfs.createReadStream(filename);
let fileChunks = [];
readstream.on('data', function (chunk) {
fileChunks.push(chunk);
});
readstream.on('end', function () {
let concatFile = Buffer.concat(fileChunks);
let imageFormated = Buffer(concatFile).toString("base64");
resolve(imageFormated)
});
})
}
// 4. Iterate though each of the images info and retrieve the file name so it can be used with gfs.createReadStream( );
const iterateImages = async (currentPlaceImages) => {
let imagesFormattedArray = [];
for (var i = 0; i < currentPlaceImages.length; i++) {
let filename = currentPlaceImages[i].filename;
// console.log(filename);
let imageFormated = await createStream(filename);
// console.log(imageFormated);
imagesFormattedArray.push(imageFormated)
if (i === currentPlaceImages.length - 1) {
return imagesFormattedArray
}
}
}
// 3. favPlaces represents a field-value pair of each document that contains an object of ‘favorite places’, each of which with a ‘placeImage’ array of all the images associated with a place
const getImagesOfPlace = async (favPlaces) => {
let imagesStreamArray = [];
for (var w = 0; w < favPlaces.length; w++) {.
let currentPlaceImages = favPlaces[w]['placeImage'];
let imagesStream = await iterateImages(currentPlaceImages);
imagesStreamArray.push(imagesStream);
if (w === favPlaces.length - 1) {
return imagesStreamArray;
}
};
}
// 2. Loop through the documents retrieved from the database and access the field - value pair that contains the information of the images that I want to retrieve using GridFs
let arrayOfUsers = [];
const getImages = async () => {
let arrayOfFormattedImages = [];
for (var i = 0; i < users.length; i++) {
let favPlaces = users[i]['favoritePlaces'];
let stream = await getImagesOfPlace(favPlaces);
userObj['imageFormatted'] = stream;
arrayOfUsers.push(userObj);
}
};
await getImages();
这是流程的可视化表示
如前所述,这种方法需要很长时间才能获得服务器响应。如果有人知道更好、更有效、更快速的方法,请告诉我。
谢谢!
因为您使用 for
循环,图像将一个接一个地加载而不是一次全部加载,循环将迭代然后等待然后再次迭代并等待等等......你需要开火一次完成所有异步操作并等待所有异步操作完成,Promise.all
使用 Array.map
是一种方法。尝试这样的事情:
const iterateImages = (currentPlaceImages) => {
return Promise.all(
currentPlaceImages.map(async (i) => {
const filename = i.filename;
return createStream(filename);
})
);
};
const getImagesOfPlace = async (favPlaces) => {
return Promise.all(
favPlaces.map(async (p) => {
const currentPlaceImages = p.placeImage;
return iterateImages(currentPlaceImages);
})
);
};
const getImages = async () => {
return Promise.all(
users.map(async (u) => {
const favPlaces = u.favoritePlaces;
const stream = await getImagesOfPlace(favPlaces);
u.imageFormatted = stream;
return u
})
);
};
let arrayOfUsers = await getImages();
我有一个 Web 应用程序,它使用 GridFS 从 MongoDB 存储和检索图像。我的问题是,当用户发出提示服务器从数据库中检索图像的请求时,需要很长时间。
例如,仅检索数据库中的两个文档然后遍历每个文档以获取与每个文档关联的图像的请求最多可能需要 45 秒。在这种情况下,从数据库中检索到的图像总量约为 10。
这是我的方法:
// 1. Query the database
var users = await User.find({ 'key’': value });
// 5. Use GridFs to get the image and return the result
const createStream = (filename) => {
return new Promise((resolve, reject) => {
let readstream = gfs.createReadStream(filename);
let fileChunks = [];
readstream.on('data', function (chunk) {
fileChunks.push(chunk);
});
readstream.on('end', function () {
let concatFile = Buffer.concat(fileChunks);
let imageFormated = Buffer(concatFile).toString("base64");
resolve(imageFormated)
});
})
}
// 4. Iterate though each of the images info and retrieve the file name so it can be used with gfs.createReadStream( );
const iterateImages = async (currentPlaceImages) => {
let imagesFormattedArray = [];
for (var i = 0; i < currentPlaceImages.length; i++) {
let filename = currentPlaceImages[i].filename;
// console.log(filename);
let imageFormated = await createStream(filename);
// console.log(imageFormated);
imagesFormattedArray.push(imageFormated)
if (i === currentPlaceImages.length - 1) {
return imagesFormattedArray
}
}
}
// 3. favPlaces represents a field-value pair of each document that contains an object of ‘favorite places’, each of which with a ‘placeImage’ array of all the images associated with a place
const getImagesOfPlace = async (favPlaces) => {
let imagesStreamArray = [];
for (var w = 0; w < favPlaces.length; w++) {.
let currentPlaceImages = favPlaces[w]['placeImage'];
let imagesStream = await iterateImages(currentPlaceImages);
imagesStreamArray.push(imagesStream);
if (w === favPlaces.length - 1) {
return imagesStreamArray;
}
};
}
// 2. Loop through the documents retrieved from the database and access the field - value pair that contains the information of the images that I want to retrieve using GridFs
let arrayOfUsers = [];
const getImages = async () => {
let arrayOfFormattedImages = [];
for (var i = 0; i < users.length; i++) {
let favPlaces = users[i]['favoritePlaces'];
let stream = await getImagesOfPlace(favPlaces);
userObj['imageFormatted'] = stream;
arrayOfUsers.push(userObj);
}
};
await getImages();
这是流程的可视化表示
如前所述,这种方法需要很长时间才能获得服务器响应。如果有人知道更好、更有效、更快速的方法,请告诉我。
谢谢!
因为您使用 for
循环,图像将一个接一个地加载而不是一次全部加载,循环将迭代然后等待然后再次迭代并等待等等......你需要开火一次完成所有异步操作并等待所有异步操作完成,Promise.all
使用 Array.map
是一种方法。尝试这样的事情:
const iterateImages = (currentPlaceImages) => {
return Promise.all(
currentPlaceImages.map(async (i) => {
const filename = i.filename;
return createStream(filename);
})
);
};
const getImagesOfPlace = async (favPlaces) => {
return Promise.all(
favPlaces.map(async (p) => {
const currentPlaceImages = p.placeImage;
return iterateImages(currentPlaceImages);
})
);
};
const getImages = async () => {
return Promise.all(
users.map(async (u) => {
const favPlaces = u.favoritePlaces;
const stream = await getImagesOfPlace(favPlaces);
u.imageFormatted = stream;
return u
})
);
};
let arrayOfUsers = await getImages();