Reputation: 23
Let's say I have a simple database and I'm trying to find all users who speak both English and Spanish and/or English and French (but not Spanish and French). I have a users
table with a handful of records set up like this:
{
"username": "jdoe",
"languages": ["english", "spanish", "french"]
}
I get the expected results when I search like this:
db.find({ "languages" : { $all:['english', 'spanish'], $all:['english', 'french'] } })
But I'm not sure how to do it with Cake. I can match a single language pair like so:
$this->User->find('all', array('conditions' => 'User.languages' => array('$all' => array('english', 'spanish'))));
But I'm stuck on how to search for multiple pairs; an array of arrays doesn't seem to do it.
This is a project someone else started, so I'm not particularly familiar with the nuances of CakePHP or MongoDB; I have a feeling I'm overlooking something obvious. Any ideas?
Upvotes: 1
Views: 1872
Reputation: 6922
Your shell query example may have returned the expected results for your test data, but it's technically incorrect since you're clobbering the $all
property in the query object. Using the top-level $or
operator, the correct query would be:
db.users.find({"$or": [
{"languages": {"$all": ["english", "spanish"]}},
{"languages": {"$all": ["english", "french"]}}
]});
This translates to CakePHP as:
$results = $this->User->find('all', array('conditions' => array(
'$or' => array(
array('User.languages' => array('$all' => array('english', 'spanish'))),
array('User.languages' => array('$all' => array('english', 'french'))),
),
)));
I tested this using the following fixture data (sans _id
's) in a CakePHP app:
{ "username" : "john", "languages" : [ "english", "spanish", "french" ] }
{ "username" : "mike", "languages" : [ "spanish", "french" ] }
{ "username" : "bill", "languages" : [ "english" ] }
{ "username" : "fred", "languages" : [ "english", "french" ] }
{ "username" : "luke", "languages" : [ "english", "spanish" ] }
John, Fred and Luke are returned.
Upvotes: 4