【问题标题】:Meteor return length of array in mongodbmongodb中数组的流星返回长度
【发布时间】:2015-07-17 20:10:30
【问题描述】:

在我的用户个人资料集合中,我有一个包含图像对象的数组。

一个用户的个人资料集合中最多可以有 3 张图片。如果用户有 3 个,则抛出已达到最大值的错误。用户可以选择在前端自己删除图像。

我认为解决方案是使用 $size 检查数组的长度。如果小于 3,则插入图片,否则抛出错误。

我正在使用 tomi:upload-jquery 包。

客户:

  Template.uploadImage.helpers({
    uploadUserData: function() {
        return Meteor.user();
    },
    finishUpload: function() {
        return {
            finished: function(index, fileInfo, context) {

                Meteor.call('insert.profileImage', fileInfo, function(error, userId) {
                    if (error) {
                        // todo: display modal with error
                        return console.log(error.reason);
                    } else {
                        // console.log('success ' +userId);
                        // console.log('success ' + fileInfo);
                    }
                });
            }
        };
    }
});

我使用的方法(服务器):

'insert.profileImage': function(postImage) {
    check(postImage, Object);

    // check array profile.images max 3

    Meteor.users.update(this.userId, {
        $push: {
            'profile.images': postImage
        }
    });
},

【问题讨论】:

  • 第四张图片是不允许的,还是应该替换之前的图片?您的模板代码正在更新配置文件,这让客户非常信任。您是否在应用程序的其他任何地方都这样做?我问是因为这里更好的解决方案是使用配置文件更新的方法。
  • 因此,如果我理解正确,您要求的解决方案不包括替换 images 数组中的项目?您应该在问题本身中对其进行编辑,这不是很清楚。
  • @DavidWeldon 嗯,是的,我实际上在几个地方进行了更新。但是我这里用的方法对吗?
  • @Kyll 让问题更清楚

标签: arrays mongodb meteor


【解决方案1】:

您可以使用$where 操作符通过函数来​​实现:

'insert.profileImage': function(postImage) {
    var updateResults;
    check(postImage, Object);

    updateResults = Meteor.users.update(
    {
        _id : this.userId,
        $where : 'this.profile.images.length < 3' //'this' is the tested doc
    },
    {
        $push: {
            'profile.images': postImage
        }
    });

    if(updateResults === 0) {
       throw new Meteor.Error('too-many-profile-images', 
         'A user can only have up to 3 images on his/her profile');
    }
},

Mongo 文档 warns about potential performance issues(如果您在商店的所有文档上运行 JavaScript 函数,您会感到很意外)但由于我们也通过 _id 进行搜索,所以我想应该没问题。

这样,如果用户有太多图像,更新就不会运行。您还可以检查受影响文档的数量(return value of the update)以了解是否发生了某些事情。如果什么都没发生(返回0),则可能性不大:用户的图片太多。

【讨论】:

  • 谢谢!我一直在测试和弄乱代码,但 updateResults 总是返回 1
  • 嗯,很奇怪,我看不出有什么问题。我会做一些测试。天哪,这里似乎没有人在第一次尝试时给出正确答案>.>
  • @flowen 找到了!实际上,您不能使用 $where 传递函数,您必须在字符串中传递嵌入的 JavaScript(参见 this Google Groups discussion)。测试了一下,效果很好。
  • 哈哈是的,也许是我的光环。这确实有效!非常感谢。所以我这里的学习是使用 $where 传入 JS 表达式并检查它。永远不会假设为此使用 $where 。谢谢!
【解决方案2】:

使用$exists 运算符来检查是否存在所有至少具有第四个配置文件图像数组元素(索引位置为 3)且带有 dot notation 的文档。例如,您可以使用它来检查profile.image 数组的大小是否大于3,使用find() 方法如下:

var hasSizeGreaterThanThree = Meteor.users.find( 
    {
        '_id': this.userId, 
        'profile.image.3': { '$exists': true }
    }).count() > 0;

所以你可以在你的代码中使用它:

'insert.profileImage': function(postImage) {
    check(postImage, Object);

    // check array profile.images max 3
    var hasSizeGreaterThanThree = Meteor.users.find( 
        {
            '_id': this.userId, 
            'profile.image.3': { '$exists': true }
        }).count() > 0;

    if (!hasSizeGreaterThanThree){
        Meteor.users.update(this.userId, {
            $push: {
                'profile.images': postImage
            }
        });
    }
},

【讨论】:

  • 感谢您的回复!我收到一个错误: $err" : "Can't canonicalize query: BadValue $size needs a number", "code" : 17287
  • @flowen 很抱歉给你错误的代码,它未经测试。请查看我的更新答案,谢谢。
  • count() &gt; 0 是一个条件,用于检查 find() 游标与'profile.image.3': { '$exists': true } 查询返回的文档数是否大于 0,如果是,则表示存在文档在数组中具有三个以上的配置文件图像。希望这有助于理解我们为什么需要这种情况。您也可以使用.count() === 0 来检查文档是否少于 4 个元素。
  • 好的,这个新变化似乎不起作用,因为 hasSizeGreaterThanThree 总是返回 false。
  • 这意味着用户的个人资料图像数组大小小于 4,这不是您所期望的吗?你能在mongoshell中对你知道数组大小大于3的特定用户做一个简单的查询,看看结果是否相符?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-10
  • 2014-02-18
  • 2023-03-06
  • 1970-01-01
相关资源
最近更新 更多