Jack Reid
Jack Reid

Reputation: 87

Meteor MongoDB: $pull/$pullAll error

So I'm trying to write an event handler and method that adds the username of a post and adds it to the array following under the Meteor user's profile document. If it's already there, it removes the name from the user's following array, unfollowing the user.

The event handler calls userFollow method that checks for already following and all that. That stuff all works. What doesn't work is the actual MongoDB functions. Something in the query below throws Exception while invoking method 'userFollow' MongoError: Cannot apply $pull/$pullAll modifier to non-array. I know for a fact that the under the users collection, user>profile>following is an array of usernames.

Why am I getting this error with this query?

userFollow: function(postAttributes) {
    var user = Meteor.user();
    var targetUser = postAttributes.username;

/* Check if the user is logged in, then check
*  if the user is tying to follow themself. */
if (!user) {
    throw new Meteor.Error(401, "You need to login to follow.");
}
    if (user.username == targetUser) {
        throw new Meteor.Error(401, "You can can't follow yourself.");
    }

    /* Checks if the target user is already in the
    *  current user's following array. */
    function userFollowed(targetUser, user) {
        for (var i in user.profile.following) {
            if (user.profile.following[i] == targetUser) {
                return true;
            }
        }
        return false;
    }

    /* Uses userFollowed to either follow or unfollow
    *  the user in question. */
    if (userFollowed(targetUser, user) == true ) {
        console.log("Unfollowing");

        Meteor.users.update(
            { _id: user._id },
            { $pull: { profile: { following: targetUser } } },
            { multi: true }
        );

    } else if (userFollowed(targetUser, user) == false ) {
        console.log("Following");
        Meteor.users.update(
            { _id: user._id },
            { $push: { profile: { following: targetUser } } }
        );
    } else {
        throw new Meteor.Error(401, "The userFollowed check failed.");
    }

}

Upvotes: 0

Views: 296

Answers (1)

David Weldon
David Weldon

Reputation: 64312

I believe the syntax should be:

{$push: {'profile.following': targetUser}}

However, you may want to use $addToSet instead:

{$addToSet: {'profile.following': targetUser}}

That will ensure you only ever have unique values in the following array. I realize you are checking for this with userFollowed, but it's a good pattern to use anyway.

Note also that you can replace userFollowed with this:

var userFollowed = _.contains(user.profile.following, targetUser);

Upvotes: 1

Related Questions