1

For MongoDB 4.4.6

For a collection with an array - If I use

db.fighters.find({"close_attacks": {$size: 3}},
                 {"_id": 0, "biography": 0})
           .pretty()
db.fighters.find({"close_attacks.2" : { $exists: true }},
                 {"_id": 0, "biography": 0})
           .pretty()
db.fighters.find({"close_attacks.3" : { $exists: true }},
                 {"_id": 0, "biography": 0})
           .pretty()

All work in peace

I want work with >=# (i.e >=3), I did do a research, and in many posts in SO appear two options, one already shown above: working with the index of the array and #exists, the other is working with $where

So in Compass through _mongosh beta I tried:

db.fighters.find({$where: "this.close_attacks.length >= 3"},
                 {"_id": 0, "biography": 0})
           .pretty()

and arises

MongoError: TypeError: this.close_attacks is undefined :
@:1:15

If I remove this

db.fighters.find({$where: "close_attacks.length >= 3"},
                 {"_id": 0, "biography": 0})
           .pretty()

it arises

MongoError: ReferenceError: close_attacks is not defined :
@:1:15

What is missing or wrong?

Manuel Jordan
  • 15,253
  • 21
  • 95
  • 158

1 Answers1

1

You can use $expr operator to use aggregation operator $gte and $size,

Aggregation Alternatives Preferred
Starting in MongoDB 3.6, the $expr operator allows the use of aggregation expressions within the query language.

db.fighters.find({
  $expr: {
    $gte: [{ $size: "$close_attacks" }, 3]
  }
},
{"_id": 0, "biography": 0}).pretty()

MongoError: The argument to $size must be an array, but was of type: missing

You can avoid such error by checking its type using $type,

db.fighters.find({
  $and: [
    { close_attacks: { $type: "array" } },
    {
      $expr: {
        $gte: [{ $size: "$close_attacks" }, 3]
      }
    }
  ]
},
{"_id": 0, "biography": 0}).pretty()

NOTE:
Starting in MongoDB 4.4, $where no longer supports the deprecated BSON type JavaScript code with scope (BSON type 15). The $where operator only supports BSON type String (BSON type 2) or BSON type JavaScript (BSON type 13). The use of BSON type JavaScript with scope for $where has been deprecated since MongoDB 4.2.1.

The two blocks are available in $where

turivishal
  • 34,368
  • 7
  • 36
  • 59
  • My 2 `$where` expressions what BSON types are? They are failing due that, right? Seems the former is 15, but for the latter I'm not sure what type is – Manuel Jordan Jun 01 '21 at 15:55
  • Something is wrong - it arises: `MongoError: The argument to $size must be an array, but was of type: missing` – Manuel Jordan Jun 01 '21 at 16:11
  • 1
    your first `$where` query with `this` is correct, but yah it is failing because of type 15. `The argument to $size must be an array` it is because there different type value in `close_attacks` field. so $size operator needs only array type input. – turivishal Jun 01 '21 at 16:17
  • The `close_attacks` is an array based on String - how fix that error message? – Manuel Jordan Jun 01 '21 at 16:18
  • 1
    see i have updated answer, check condition by field type should be an array. – turivishal Jun 01 '21 at 16:19
  • Thank you, just being curious, the first approach when should work without any problem? I saw here the same approach - https://stackoverflow.com/a/48410837/3665178 - now what is mandatory the second approach? – Manuel Jordan Jun 01 '21 at 16:20
  • what is first approach? are you talking about $where or $expr? or $expr with $type? – turivishal Jun 01 '21 at 16:23
  • First approach without `$and: [...`, second approach with `$and: [` - of your two solutions – Manuel Jordan Jun 01 '21 at 16:24
  • 1
    its just wrapper, just for a clear view and make sure that you are managing conditions properly, can use without it `{ close_attacks: { $type: "array" }, $expr: { $gte: [{ $size: "$close_attacks" }, 3] } }`, there are parcing issues in some language sdk so that is why I have wrapped it to `$and`. – turivishal Jun 01 '21 at 16:29
  • 1
    for information: in background mongodb will wrap that conditions by `$and` operator you can see it using `explain()` function. – turivishal Jun 01 '21 at 16:31
  • `"there are parcing issues in some language sdk so that is why I have wrapped it to $and"` Interesting, I am just using MongoDB Compass – Manuel Jordan Jun 01 '21 at 16:32
  • 1
    *I am just using MongoDB Compass* sorry for that I missed that, I just used the standard approach. – turivishal Jun 01 '21 at 16:36
  • Don't worry, but if I used Compass through two ways: "Documents -> Filters" and its own "mongosh beta" terminal - not sure what do you mean with _"standard approach"_ – Manuel Jordan Jun 01 '21 at 16:40
  • 1
    called mongodb implicit approach, implicitly it will wrap in `$and` to execute match in sequence. see this [question](https://stackoverflow.com/questions/54750316/mongodb-difference-between-condition-with-and-operator-and-without-the-operator). – turivishal Jun 01 '21 at 17:04