Reputation: 1187
I have a MongoDB document that is structured similar to the structure below follows. I am searching based on people.search_columns.surname and people.columns.givenname. So for example, when I search for the given name of "Valentine", I want to get the document back, but Nicholas Barsaloux should not be included.
Data structure:
[_id] => MongoId Object (
[$id] => 53b1b1ab72f4f852140dbdc9
)
[name] => People From 1921
[people] => Array (
[0] => Array (
[name] => Barada, Valentine
[search_columns] => Array (
[surname] => Array (
[0] => Mardan,
[1] => Barada
)
[givenname] => Array (
[0] => Valentine
)
)
)
[1] => Array (
[name] => Barsaloux, Nicholas
[search_columns] => Array (
[surname] => Array (
[1] => Barsaloux
)
[givenname] => Array (
[0] => Nicholas
)
[place] => Array (
)
)
)
)
Here is the code I was working on:
$criteria = array("people" => array(
'$elemMatch' => array("givenname" => "Valentine")
));
$projection = array("people" => true);
$documents_with_results = $db->genealogical_data->find($criteria, $projection)->skip(0)->limit(5);
Currently that code returns zero results.
Upvotes: 1
Views: 998
Reputation: 151112
Since the arrays are nested you cannot use basic projection as you can with find. Also in order to "filter" the array contents from a document you need to "unwind" the array content first. For this you use the aggregation framework:
$results = $db->genealogical_data->aggregate(array(
array( '$match' => array(
'people.search_columns.givenname' => 'Valentine'
)),
array( '$unwind' => '$people' ),
array( '$match' => array(
'people.search_columns.givenname' => 'Valentine'
)),
array( '$group' => array(
'_id' => '$id',
'name' => array( '$first' => '$name' ),
'people' => array( '$push' => '$people' )
))
));
The point of the first $match
stage is to reduce the documents that possibly match your criteria. The second time is done after the $unwind
, where the actual "array" items in the document are "filtered" from the results.
The final $group
puts the original array back to normal, minus the items that do not match the criteria.
Upvotes: 3