Find documents by the number of built-in array elements that match the condition

I am new to MongoDB and need help completing my task:

I am using MongoDB to request human action. Actions are embedded in a person’s document as follows:

{
    "_id" : ObjectId("56447ac0583d4871570041c3"),
    "email" : "email@example.net",
    "actions" : [ 
        {
            "name" : "support",
            "created_at" : ISODate("2015-10-17T01:40:35.000Z"),
        }, 
        {
            "name" : "hide",
            "created_at" : ISODate("2015-10-16T01:40:35.000Z")
        },
        {
            "name" : "support",
            "created_at" : ISODate("2015-10-17T03:40:35.000Z"),
        }
    ]
}

A person can have many actions with different names of actions ( supportand hide- only 2 examples).

I know that I could find all people with at least one action supportas follows:

db.test.find({'actions.name':'support'})

What I want to do is get all people with at least X actions support. Is this possible without using javascript syntax? Since people can have hundreds of activities, this will be slow.

, , 2 support , , , js:

db.test.find({$where: function() {
  return this.actions.filter(function(action){
    return action.name = 'support';
  }).length >= 2;
}});

/ ?

+4
2

, - .aggregate(), .

$match, , .

$redact, , , "" $gte 2. $map , false, , $setDifference. , $size .

db.test.aggregate([
    { "$match": { 
        "actions.name": "support", 
        "actions.2": { "$exists": true } 
    }},
    { "$redact": {
        "$cond": [
            { "$gte": [
                { "$size": { 
                    "$setDifference": [
                        { "$map": { 
                            "input": "$actions", 
                            "as": "action", 
                            "in": { 
                                "$cond": [
                                    { "$eq": [ "$$action.name", "support" ] }, 
                                    "$$action", 
                                    false
                                ]
                            }
                        }}, 
                        [false]
                     ]
                }}, 
                2
            ]}, 
            "$$KEEP", 
            "$$PRUNE"
        ]
    }}
])

MongoDB 3.2 $filter.

db.test.aggregate([
    { "$match": { 
        "actions.name": "support", 
        "actions.2": { "$exists": true } 
    }},
    { "$redact": {
        "$cond": [
            { "$gte": [
                { "$size": { 
                    "$filter": { 
                        "input": "$actions", 
                        "as": "action", 
                        "cond": { "$eq": [ "$$action.name", "support" ] }
                    }
                }}, 
                2
            ]}, 
            "$$KEEP", 
            "$$PRUNE"
        ]
    }}
])

@BlakesSeven:

$setDifference , "". "" "", - , , , . $filter - , , , .

+2

, Mongo.

db.test.aggregate([
{$unwind: "$actions"},
{$group: { 
  _id: { _id: "$_id", action: "$actions},
  count: {$sum: 1}
},
{$match: {$and: [{count: {$gt: 2}}, {"_id.action": "support"]}
]);

, mongo, .

:

  • unwind ,
  • group _id-action , .
  • match , .
-2

Source: https://habr.com/ru/post/1615811/


All Articles