28

What is wrong with this query? I tried to run it on mongodb server and received an error as following - "exception: bad query: BadValue unknown top level operator: $gte". Can anyone tell me what is wrong with it, please?

        db.scores.aggregate([ 
            { 
                $match: { 
                    $or: [ 
                        { $gte: [ "$score", 30 ] }, 
                        { $lte: [ "$score", 60 ] } 
                    ] 
                } 
            },
            { 
                $group: { 
                    _id: "$gamer",
                    games: { $sum: 1 }
                } 
            }
        ])

sample data :

        {
            "_id" : "545665cef9c60c133d2bce72",
            "score" : 85,
            "gamer" : "Latern"
        }

        /* 1 */
        {
            "_id" : "545665cef9c60c133d2bce73",
            "score" : 10,
            "gamer" : "BADA55"
        }

        /* 2 */
        {
            "_id" : "545665cef9c60c133d2bce74",
            "score" : 62,
            "gamer" : "BADA55"
        }

        /* 3 */
        {
            "_id" : "545665cef9c60c133d2bce75",
            "score" : 78,
            "gamer" : "l00ser"
        }

        /* 4 */
        {
            "_id" : "545665cef9c60c133d2bce76",
            "score" : 4,
            "gamer" : "l00ser"
        }

        /* 5 */
        {
            "_id" : "545665cef9c60c133d2bce77",
            "score" : 55,
            "gamer" : "FunnyCat"
        }
Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
Evaldas Raisutis
  • 1,628
  • 4
  • 18
  • 32

4 Answers4

42

You did this wrong. Should be:

db.scores.aggregate([
    { "$match": {
        "score": { "$gte": 30, "$lte": 60 }
    }},
    { "$group": {
        "_id": "$gamer",
        "games": { "$sum": 1 }
    }}
])

Which is the proper way to specify a "range" query where the actual conditions are "and" and therefore "between" the operands specified.

Neil Lunn
  • 148,042
  • 36
  • 346
  • 317
  • 15
    The crucial point being that [`$match` takes query syntax](https://docs.mongodb.org/manual/reference/operator/aggregation/match/), so you want to use the [query `$gte` operator](https://docs.mongodb.org/manual/reference/operator/query/gte/) and not the [aggregation `$gte` operator](https://docs.mongodb.org/manual/reference/operator/aggregation/gte/). (BTW, the [range query](https://docs.mongodb.org/manual/reference/method/db.collection.find/#query-for-ranges) works through use of [implicit `$and`](https://docs.mongodb.org/manual/reference/operator/query/and/).) – duozmo Feb 15 '16 at 18:34
12

Since MongoDB version 3.6, you may use $expr to use aggregate expressions within a query. So the query can be rewritten into:

db.scores.aggregate([
  {
    $match: {
      $expr: {
        $or: [
          { $gte: ["$score", 30] },
          { $lte: ["$score", 60] }
        ]
      }
    }
  },
  {
    $group: {
      _id: "$gamer",
      games: { $sum: 1 }
    }
  }
]);
socrates
  • 1,203
  • 11
  • 16
0

This might help someone like me... in my case the field has been null. and encountered this error unknown top level operator: $in , MongoDb Exception

private <T> void addQueryCondition (Query query, String field , List<T> valuesList ) {
    if (!CollectionUtils.isEmpty(valuesList)) {
        query.addCriteria(Criteria.where(field).in(valuesList).exists(true));
    }
}
SatyaRajC
  • 51
  • 7
-3

You need to include explicitly package in cmd prompt like npm i regex and change in service like as below:

const kidDetails = await this.studentModel.find({ name:{$regex: new RegExp('.*' + studName, 'i') }} );
סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68