Confused by $type

In trying to figure out the optional lab, I started experimenting with $type, and now I’m confused.

db.movies.aggregate([
  {
    $match: { writers: { $elemMatch: { $exists: true } } }
  }
]).itcount()

results in an output of: 41491

If I change the $match to:

db.movies.aggregate([
  {
    $match: { writers: { $type: "string" } }
  }
]).itcount()

I get the exact same count.

writers is supposed to be an array (of string, yes), but why doesn’t $type differentiate between those?

It is confusion indeed. Because there is 2 different $type and arrays are specials.

See both at

and

There is a note somewhere:

Behavior

$type returns documents where the BSON type of the field matches the BSON type passed to $type .

Arrays

For documents where field is an array, $type returns documents in which at least one array element matches a type passed to $type .

Querying for the Array BSON Type

With MongoDB 3.6 and later, querying for $type: "array" returns documents where the field itself is an array. Prior to MongoDB 3.6, $type: "array" returned documents where the field is an array containing at least one element of type array . For example, given the following documents:

{ “data” : [ “values”, [ “values” ] ] } { “data” : [ “values” ] }

With MongoDB 3.6 and later, the query find( {"data" : { $type : "array" } } ) returns both documents. Prior to MongoDB 3.6, the query returns only the first document.

That is why I use

    {
        '$match': {
            'writers.0': {
                '$exists': True
            }
        }
    }

to match an array. But it does not work if the array is empty. ;-(

And I use

    {
        '$match': {
            'writers.0': {
                '$type': 'string'
            }
        }
    }

to match arrays of strings.

1 Like