質問

It works like I need:

    $out = $collection->aggregate(
        array(
            '$match' => array('type' => 'chair')
        ),
        array(
                '$project' => array(
                    'chairtype' => 1,
                    'mijczjeqeo'=>1
                )
        ),
        array( 
            '$group' => array(
                '_id' => '$chairtype', 
                'MIDDLE_mijczjeqeo' => array('$avg' => '$mijczjeqeo'),
                'SUMMA__mijczjeqeo' => array('$sum' => '$mijczjeqeo')
            )
        )
);
my_dump($out);

But i need to get true data for aggregation from array in the same documents: versions[0][content][mijczjeqeo]

Please correct my script. It does not work:

$out = $collection->aggregate(
        array(
            '$match' => array('type' => 'chair')
        ),
        array(
                '$project' => array(
                    'chairtype' => 1,
                    'versions.0.content.mijczjeqeo'=>1
                )
        ),
        array( 
            '$group' => array(
                '_id' => '$chairtype', 
                'MIDDLEmijczjeqeo' => array('$avg' => '$versions.0.content.mijczjeqeo'),
                'SUMMAmijczjeqeo' => array('$sum' => '$versions[0]["content"]["mijczjeqeo"]')
            )
        )
);

no one method does not work:

'MIDDLEmijczjeqeo' => array('$avg' => '$versions.0.content.mijczjeqeo')

'SUMMAmijczjeqeo' => array('$sum' => '$versions[0]["content"]["mijczjeqeo"]')

I think the problem near .0.

I try to do it in mongo console...

db.documents.aggregate({$match:{'type':'chair'}},{$project:{'chairtype': 1, 'mijczjeqeo':1}},{$group:{'_id':'$chairtype','MID':{$avg:'$mijczjeqeo'}}})
{
    "result" : [
        {
            "_id" : "T",
            "MID" : 6.615384615384615
        },
        {
            "_id" : "G",
            "MID" : 8.310344827586206
        },
        {
            "_id" : "E",
            "MID" : 6.9523809523809526
        }
    ],
    "ok" : 1
}

db.documents.aggregate({$match:{'type':'chair'}},{$project:{'chairtype': 1, 'versions.0.content.mijczjeqeo':1}},{$group:{'_id':'$chairtype','MID':{$avg:'$versions.0.content.mijczjeqeo'}}})
{
    "result" : [
        {
            "_id" : "T",
            "MID" : 0
        },
        {
            "_id" : "G",
            "MID" : 0
        },
        {
            "_id" : "E",
            "MID" : 0
        }
    ],
    "ok" : 1
}
役に立ちましたか?

解決

Well you cannot project like that in the aggregation pipeline. If you want to act on array elements within an aggregation statement you first need to $unwind the array and then either $match the required element(s) or as in your case choose the $first item using an additional $group stage.

Your question does not show the structure of a document so I'll just use a sample, as my "chairs" collection:

{
    "_id": 1,
    "type": "chair",
    "chairtype": "A",
    "versions": [
        {
           "revision": 1,
           "content": {
               "name": "ABC",
               "value": 10
           }
        },
        {
           "revision": 2,
           "content": {
               "name": "BBB",
               "value": 15
           }
        }
    ]
}
{
    "_id": 2,
    "type": "chair",
    "chairtype": "A",
    "versions": [
        {
           "revision": 1,
           "content": {
               "name": "CCC",
               "value": 20
           }
        },
        {
           "revision": 2,
           "content": {
               "name": "BAB",
               "value": 12
           }
        }
    ]
}

Minimal, but enough to get the point. Now the aggregate statement:

db.chairs.aggregate([

    // Normal query matching, which is good
    { "$match": { "type": "chair" } },

    // Unwind the array to de-normalize
    { "$unwind": "$versions" },

    // Group by the document in order to get the "first" array element
    { "$group": { 
        "_id": "$_id", 
        "chairtype": { "$first": "$chairtype" }, 
        "versions": { "$first": "$versions" } 
    }},

    // Then group by "chairtype" to get your average values
    { "$group": { 
        "_id": "$chairtype", 
        "MID": {"$avg": "$versions.content.value"} 
    }}

])

Of course if your actual document has nested arrays then you will be "unwinding" and "matching" the required elements. But that is the general process of "narrowing down" the array contents to the elements you need.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top