MeisterEder7
MeisterEder7

Reputation: 83

Query document's array fields in PHP MongoDB using filter and options

I am using the PHP MongoDB\Driver\Manager and I want to query by creating a MongoDB\Driver\Query.

So I have the following collection design:

{
    "_comment": "Board",
    "_id": "3",
    "player": "42",
    "moves": [{
        "_id": "1",
        "piece": "b3rw4",
        "from_pos": "E2",
        "to_pos": "E4"
    }]
}

How can i query this collection to receive, for all boards of a specific player all moves with min(id)? This means I first want to filter all boards, to get only boards with player ID. Then I want to search all those board's "moves" fields, where I want the min(_id) of that "moves" field.

I currently have this query:

$filter = ['player' => '93'];
$options = [
    'projection' => ['_id' => 0,
                     'moves' => 1]
];
$query = new MongoDB\Driver\Query($filter, $options);

This results in finding all "moves" arrays by Player 93.

How can I then filter all those "moves" fields by only getting the moves with min(_id)?

Upvotes: 0

Views: 1492

Answers (1)

MeisterEder7
MeisterEder7

Reputation: 83

Ok, so I figured it out. I simply had to use an aggregation pipeline.

Here is the shell command which gives the expected output:

db.boards.aggregate( [
    {
     $match: {'player': '93'}
    },
    {
     $unwind: {path: '$moves'}
    },
    {
     $group:
       {
         _id: '$_id',
         first_move: { $min: '$moves._id' },
         from_pos : { $first: '$moves.from_pos' },
         to_pos: { $first: '$moves.to_pos' }
       }    
    }
])

Here is the corresponding PHP MongoDB code using Command and aggregate:

$command = new MongoDB\Driver\Command([
    'aggregate' => 'boards',
    'pipeline' => [
        ['$match' => ['player' => '93']],
        ['$unwind' => '$moves'],
        ['$group' => ['_id' => '$_id',
                      'firstMove' => ['$min' => '$moves._id'],
                      'from_pos' => ['$first' => '$moves.from_pos'],
                      'to_pos' => ['$first' => '$moves.to_pos']
                     ]
        ]
    ],
    'cursor' => new stdClass,
]);

$manager = new MongoDB\Driver\Manager($url);
$cursor = $manager->executeCommand('db', $command);

Upvotes: 0

Related Questions