从 MongoDB 检索图像的最佳方法是什么?

发布于 2025-01-15 04:55:42 字数 3036 浏览 4 评论 0原文

我有一个使用 GridFS 从 MongoDB 存储和检索图像的 Web 应用程序。我的问题是,当用户发出请求提示服务器从数据库检索图像时,需要很长时间。

例如,仅检索数据库中的两个文档,然后循环访问每个文档以获取与每个文档关联的图像的请求最多可能需要 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();

这是流程的直观表示 在此处输入图像描述

如前所述,这种方法需要很长时间才能获得服务器回复。如果有人知道更好、更有效、更快速的方法,请告诉我。

谢谢!

I have a web application that stores and retrieves images from MongoDB using GridFS. My issue is that when the user makes a request that prompts the server to retrieve images from the database, it takes a very long time.

For instance, a request that retrieves only two documents in the database and then loops through each document to get the images associated with each document can take up to 45 seconds. In this case, the total amount of images retrieved from the database is around 10.

Here is my approach:

// 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();

Here is a visual representation of the flow enter image description here

As mentioned, this approach takes very long to get a server response. If any one knows a better, more effective and fast way of doing this, please let me know.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

话少情深 2025-01-22 04:55:42

因为您使用 for 循环,所以图像将一个接一个地加载,而不是一次全部加载,循环将迭代然后等待,然后再次迭代并等待等等......您需要触发所有异步立即执行操作并等待所有操作完成,使用 Array.map 的 Promise.all 是一种方法。尝试这样的事情:

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();

Because you use for loops the images will load one after the other instead of all at once, the loop will iterate then await then iterate again and await and so on.... You need to fire all async actions at once and await for all of them to finish, Promise.all using Array.map is a way to do it. Try something like this:

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文