4

I am a mongo noob and am working with a mongo collection with records that look like so:

{
    "cats" [
        {
            "name": "fluffy",
            "color": "red",           
        }, 
        {
            "name": "snowball",
            "color": "white",           
        }, 
    ]
{

I would like to perform a query that gets all records that have more than 1 white cats. MapReduce looks promising, but seems like overkill. Any help is appreciated.

1

2 Answers 2

4

You can use the aggregation framework to do this. You don't need to use the $where operator.

db.collection.aggregate([
    { "$match": { "cats.color": "white" }},
    { "$project": { 
        "nwhite": { "$map": { 
            "input": "$cats", 
            "as": "c",
            "in": { "$cond": [
                { "$eq": [ "$$c.color", "white" ] },
                1, 
                0
            ]}
        }}, 
        "cats": 1
     }},
     { "$unwind": "$nwhite" }, 
     { "$group": { 
         "_id": "$_id", 
         "cats": { "$first": "$cats" }, 
         "nwhite": { "$sum": "$nwhite" }
     }},
    { "$match": { "nwhite": { "$gte" :2 } } } 
])
Sign up to request clarification or add additional context in comments.

Comments

2

Use $where. It is an especially powerful operator as it allows you to execute arbitrary javascript.

For your specific case, try this:

db.collection.find({$where: function() {
  return this.cats.filter(function(cat){
    // Filter only white cats
    return cat.color === 'white';
  }).length >= 2;
}});

2 Comments

if i would like to match an extra field which is outside cats array for eg: cat type:1 how will i do that?
It's just pure javascript at this point, so within the $where function you'd simply extend your boolean return with && this.type === 1. The key here is that the this value within the where function is the document you're iterating over.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.