21

I want to project a collection applying exporting a value only if a field is inside a range.

Sort of:

db.workouts.aggregate({
 $match: { user_id: ObjectId(".....") }
},
{
 $project: { 
        '20': { $cond: [ {$gt: [ "$avg_intensity", 20]} , '$total_volume', 0] }
    }    
 })

I need to get the value only if the avg_intensity is inside a certain range. I will then group and sum on the projection result.

What I am trying to do is applying a $gt and $lt filter but with no much success.

db.workouts.aggregate(
{
   $match: { user_id: ObjectId("....") }
},
{
$project: { 
        '20': { $cond: [ [{$gt: [ "$avg_intensity", 20]}, {$lt: [ "$avg_intensity", 25]}] ,    '$total_volume', 0] }
    }    
 })

How may I apply both $gt and $lt conditions?

4 Answers 4

32

To combine logical conditions under a $cond operator then wrap the conditions with an $and operator:

db.workouts.aggregate([
    { "$match": { "user_id": ObjectId("....") }},
    { "$project": { 
       "20": { "$cond": [
           { "$and": [ 
               { "$gt": [ "$avg_intensity", 20 ] },
               { "$lt": [ "$avg_intensity", 25 ] }
           ]},    
           "$total_volume", 
           0
       ]}
   }}
])
Sign up to request clarification or add additional context in comments.

Comments

3

filter with multiple condition:

let booking = await Booking.findOne(
    { userId: req.currentUser?.id },
    {
      id: 1,
      status: 1,
      cart: {
        $filter: {
          input: '$cart',
          as: 'c',
          cond: {
            $and: [
              { $eq: ['$$c.date', cDate] },
              { $eq: ['$$c.product', new mongoose.Types.ObjectId(productId)] },
            ],
          },
        },
      },
      version: 1,
    }
  ).populate('cart.product', {
    id: 1,
    name: 1,
    thumbnail: 1,
    photos: 1,
    mrp: 1,
    minPrice: 1,
  });

Comments

1

If I got your requirements right you should put the filter in the match part of the pipeline:

db.workouts.aggregate( [
  { $match: { user_id: ObjectId("...."), "avg_intensity": { $gt: 20, $lte: 25 } } },
  { $group: { _id: ..., count: ... } }
] );

1 Comment

This is a solution but I would end making more queries. I forgot to mention that I need to make more subsets. Es: take any result between 20 and 40, then take results between 40 and 60 etc.... So I would like to group them cause I could have more subsets as result running the same aggregation
0

In the following way we can aggregate, Here i using two conditions which are city,year

db.getCollection('geolocations').aggregate(
   [{$unwind : '$geolocation'},
     {
       $group:
         {
           _id: {city:"$geolocation.city",year: { $year: "$geolocation.date" }},
           count: { $sum: 1 }
         }
     }
   ]
)

Output:

/* 1 */
{
    "_id" : {
        "city" : "Noida",
        "year" : 2020
    },
    "count" : 1.0
}

/* 2 */
{
    "_id" : {
        "city" : "Villupuram",
        "year" : 2020
    },
    "count" : 1.0
}

/* 3 */
{
    "_id" : {
        "city" : "Chennai",
        "year" : 2020
    },
    "count" : 2.0
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.