0
{
  "_id": ObjectId("53ab1d2c256072374a5cc63f"),
  "title": "10% Off",
  "endDate": "2015-05-08",
  "limit" : "limited",
  "redemptions": [
    "1f7f5f96be3a",
    "kf40vksk03ps"
  ]
}
{
  "_id": ObjectId("53ab1d2c25607sfdgs74a5cc63f"),
  "title": "20% Off",
  "endDate": "2015-06-07",
  "limit" : "unlimited",
  "redemptions": [
    "1f7f5f96be3a",
    "1f7f5f96be3a",
    "kf40vksk03ps"
  ]
}

Story: a person can redeem a coupon 2 times. After 2 times, don't return it. How can I check that a value appears less than 2 times??

Wish it was as easy as:

{ 'redemptions' : { $exists: true }, $where : 'this.redemptions.$.1f7f5f96be3a.length < 2' }

How can I get a count for how many times a specific value is in an array and compare on that?

Edit So to add some fun. I updated my schema, so I need to put that into a conditional. If limit = 'unlimited' { return record } if limit = 'limited' { return only if array has less than 2 values = '1f7f5f96be3a'

1 Answer 1

2

You can do what you want with aggregation framework:

db.collection.aggregate([
    /* find only documents that have redemption key */
    { $match : { redemptions : { $exists: true }}},
    /* unwind the redemptions array so we can filter documents by coupons */
    { $unwind : "$redemptions" },
    /* filter only coupons you're looking for */
    { $match : { redemptions : "1f7f5f96be3a"}},
    /* group the documents back so we can calculate the count */
    { $group : { _id : "$_id",
                 title : { $first : "$title" },
                 endDate : { $first : "$endDate" },
                 count :  {$sum : 1 }}},
    /* finally, count the documents that have less than 2 coupons */
    { $match : { count : { $lt :2 }}}
]);

Edit:

You just need to change the $group and last $match stages:

{ $group : { _id : "$_id",
            title : { $first : "$title" },
            endDate : { $first : "$endDate" },
            limit : { $first : "$limit" },
            count :  {$sum : 1 }}},
/* finally, count the documents that have less than 2 coupons 
   or have limit "unlimited */
{ $match : { $or : [{ count : { $lt :2 }}, {limit : "unlimited"}]}}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much, got me much closer. So to add some fun... I updated my schema, so I need to put that into a conditional. if limit = 'unlimited' { return record } if limit = 'limited' { return only if array has less than 2 values = '1f7f5f96be3a' Anyone of doing that. Basically what you did but in a conditional?

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.