使用模式方法在 Mongoose For 循环中保存项目

Posted

技术标签:

【中文标题】使用模式方法在 Mongoose For 循环中保存项目【英文标题】:Saving Items In Mongoose For Loop With Schema Methods 【发布时间】:2015-02-12 13:25:16 【问题描述】:

如果我附加任何额外的验证方法,我会在保存通过 for 循环运行的项目时遇到问题。基本上,我正在构建一个 instagram API 应用程序,它允许编辑者删除不合时宜的照片。照片分批从 Instagram 中提取 20 张并显示给编辑。如果编辑者点击一张照片,它首先会按 ID 被放入“黑名单”数据库,然后从主照片数据库中删除。

为了不让列入黑名单的照片重新出现在提要中,在将项目保存到主照片数据库之前,它需要根据黑名单检查照片的 Instagram ID。为此,我使用了 Schema 方法。

现在的问题是,我只能将一张照片保存到数据库中。如果我取出方法检查,那么我得到了全部 20 个。

这是我的主要创建控制器:

exports.create = function(req, res) 

var topic = req.body.topic || 'nyc';

var path = 'https://api.instagram.com/v1/tags/' + topic + '/media/recent?client_id=' + 'XXXXXXXXXX';


request.get(url: path, function(err, response)

  if (err)
    console.log('Failed to get data: ', err);
    return res.status(400).json(error: 'Not allowed');
  

  else

    // ------------------------------------------------
    // Make sure we have JSON
    //

    var body = JSON.parse(response.body);



    // ------------------------------------------------
    // Loop through each response
    //

    for (var i = 0; i < body.data.length; i++ )
      var photoData = body.data[i];


      // ------------------------------------------------
      // If there is no caption, skip it
      //

      if (!photoData.caption)
        text = '';
      
      else
        text = photoData.caption;
      

      // ------------------------------------------------
      // Create new photo object
      //

      var photo = new Photo(
        link: photoData.link,
        username: photoData.user.username,
        profilePicture: photoData.user.profile_picture,
        imageThumbnail: photoData.images.thumbnail.url,
        imageFullsize: photoData.images.standard_resolution.url,
        caption: text,
        userId: photoData.user.id,
        date: photoData.created_time,
        _id: photoData.id
      );

      photo.checkBlacklist(function(err, blacklist)

        if (!blacklist)
          photo.save(function(err, item)
            if (err)
              console.log(err);
            

            console.log('Saved', item);
          )
        

      );

      // -------------------------------------------------
      //
      // Save
      // 
      // -------------------------------------------------

     // END FOR LOOP

    console.log('Photos saved');
    return res.json(201, msg: 'Photos updated' );
  
);
;

这是我的照片架构:

'use strict';

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var Blacklist = require('../blacklist/blacklist.model');

var PhotoSchema = new Schema(
  created: type: Date, default: Date.now(),
  date: String,
  link: String,
  username: String,
  profilePicture: String,
  imageThumbnail: type: String, unique: true,
  imageFullsize: String,
  caption: String,
  userId: String,
  _id: type: String, unique: true
);


PhotoSchema.methods.checkBlacklist = function(callback)

  return Blacklist.findById(this._id, callback);

;


module.exports = mongoose.model('Photo', PhotoSchema);

奇怪的是,我在创建控制器中收到了所有 20 次保存的控制台消息: console.log('已保存', item);

但实际上只保存了一张照片。任何想法为什么?

谢谢

【问题讨论】:

当您必须对数组中的项目执行相同的异步任务时,不要使用常规的for 循环。查看async.each,它更适合您的场景。 对此一无所知。立即完美运行。也许提供答案,以便我可以标记它?非常感谢 【参考方案1】:

当您必须对数组中的项目执行相同的异步任务时,不要使用常规的 for 循环。查看async.each,它更适合您的场景,例如(只是代码的else 部分):

var body = JSON.parse(response.body);

async.each(body.data, function (photoData, callback) 

  // ------------------------------------------------
  // If there is no caption, skip it
  //

  if (!photoData.caption)
    text = '';
  
  else
    text = photoData.caption;
  

  // ------------------------------------------------
  // Create new photo object
  //

  var photo = new Photo(
    link: photoData.link,
    username: photoData.user.username,
    profilePicture: photoData.user.profile_picture,
    imageThumbnail: photoData.images.thumbnail.url,
    imageFullsize: photoData.images.standard_resolution.url,
    caption: text,
    userId: photoData.user.id,
    date: photoData.created_time,
    _id: photoData.id
  );

  photo.checkBlacklist(function(err, blacklist)

    if (!blacklist)
      photo.save(function(err, item)
        if (err)
          console.log(err);
        

        console.log('Saved', item);
        callback();
      );
    

  );

, function (error) 
  if (error) res.json(500, error: error);

  console.log('Photos saved');
  return res.json(201, msg: 'Photos updated' );
);

别忘了安装

npm install async

并要求async:

var async = require('async');

【讨论】:

我认为您将获得与列表长度成正比的堆栈深度是否正确?即它递归到回调,然后再次每个函数? 根据文档 - 是的,除非您明确推迟回调以便它在另一个滴答声中运行:“出于性能原因,异步不会防止同步迭代。如果您仍然遇到堆栈溢出,您可以按照上面的建议推迟,或者用 async.ensureAsync 包装函数“caolan.github.io/async 这是唯一有效的答案,但它让我心烦意乱,这么明显的问题怎么可能没有在猫鼬中开箱即用的解决方案。无论如何,谢谢罗德里戈!【参考方案2】:

递归求解如何

                                saveGames = (depth) => 
                                    if (depth > 0) 
                                        var newGame = new Game( user: user._id );
                                        newGame.save((err, game) => 
                                            if (err) 
                                                console.log(err);
                                                return res.status(203).json(
                                                    title: 'error',
                                                    error:  message: 'Error Saving Games' 
                                                );
                                            
                                            user.games.push(game);
                                            user.save((err, user) => 
                                                if (err) 
                                                    console.log(err);
                                                    return res.status(203).json(
                                                        title: 'error',
                                                        error:  message: 'Error Saving Games' 
                                                    );
                                                
                                                saveGames(depth - 1);
                                            );
                                        );
                                    
                                
                                saveGames(5);

【讨论】:

以上是关于使用模式方法在 Mongoose For 循环中保存项目的主要内容,如果未能解决你的问题,请参考以下文章

如何在 mongoose 中使用 update many 来循环遍历 8 个元素并将它们放入该模式中的数组中

Node.js/Mongoose 等待异步 For 循环

Mongoose:如何使用来自模式的数据(产品值)使用方法填充另一个模式()中的字段?

Mongoose 模式实例方法不是函数

循环遍历 Mongoose 结果返回未定义

如何在 Mongoose 的不同文件中分离模式、方法和静态