javascriptmeteorminimongo

"Unrecognized logical operator: $in" Mongo.collection update


I'm getting this error:

"Unrecognized logical operator: $in"

while using this query:

this.update(
            {}, {
                $pull: {
                    words: {
                        $in:['string', 'string1']
                    }
                }
            }, {
                multi: true
            });

I'm calling within a es6 class that extends Mongo.Collection in the client, everything else thus far (inserts, remove) has worked and I'm not modifying the update method in any way. The collection is a local collection declared this way:

WordsList = new WordCollection('words', {connection: null});)

The query is very similar to the example in the documentation here and actually, I can reproduce the same error while trying to recreate this example on the console as well.

I'm using Meteor 1.4.4.1 with MongoDB 3.2.12

For some reason I can't yet pin down, I can trace the error to Mongo compiling the query mapping it to logical operators ($and, $or) instead of element (comparison query) operators ($in, $eq)


Solution

  • It is possible to modify multiple values in a local collection, however there is a limitation in what selectors or modifiers can be used, as the client-side collection users MiniMongo, which implements a subset of the MongoDB functionality.

    This particular case is a shortcoming of MiniMongo, where a logical Matcher is used in $pull expressions, as indicated in a comment in the $pull implementation:

        // XXX Minimongo.Matcher isn't up for the job, because we need
        // to permit stuff like {$pull: {a: {$gt: 4}}}.. something
        // like {$gt: 4} is not normally a complete selector.
        // same issue as $elemMatch possibly?
    

    (source: Meteor source code)

    This is from 2013, so there is not much hope for it to change without a PR.

    Specifically, the matcher only allows you to use logical selectors: "$and", "$or", "$nor", "$where", "$comment". That's why you cannot use $in, which is implemented in ELEMENT_OPERATORS.

    As a workaround (and since this is only client-side), you can use:

    valueArray.forEach(val => WordsList.update({}, {$pull: {words: val}}, {multi: true}));