Example of a Mongo Entry:
array(
'name' => 'blog one',
'blogCategory' => array(
'displayAndLightMeasurement' => '1',
'LEDAndDisplayTestInstrument' => '0'
)
);
A Query like this works fine:
$blogInfoRaw = $collection->find(array('blogCategory' => array('displayAndLightMeasurement' => '1')));
When I try to '$or' query like this:
$blogInfoRaw = $collection->find(array('$or' => array('blogCategory' => array('displayAndLightMeasurement' => '1')),array('blogCategory' => array('LEDAndDisplayTestInstrument' => '1'))));
I get this error:
$or requires nonempty array
What am I doing wrong?
You really meant to use "dot notation" to reference the embedded fields:
$blogInfoRaw = $collection->find(
array(
'$or' => array(
array( 'blogCategory.displayAndLightMeasurement' => '1' ),
array( 'blogCategory.LEDAndDisplayTestInstrument' => '1')
)
)
);
Otherwise the notation you are using implies that the "only" elements present in the embedded level are those that you specify. This is not true since there are multiple keys. So "dot notation" solves this problem by referencing the distinct keys.
PHP array notation does not help here, but the $or needs to be a wrapping "real" array as in [] also.
Issuing a json_encode often helps when comparing to the official MongoDB examples.
Related
Hello i want to use an array as condition.
For example i have services with a zip as combination
12345 => cleaning,
54321 => cleaning
now i build my array together in a foreach loop
$searcharray = [];
foreach($services as $key => $val){
searcharray[] = array('service' => $val['service'], 'zip' => $val['zip']);
}
My search array lookes like this:
[
(int) 0 => [
'service' => 'cleaning',
'zip' => '12345'
],
(int) 1 => [
'service' => 'cleaning',
'zip' => '54321'
]
]
Then i try to get the data from my request table
$this->loadModel('Requests');
$openrequests = $this->Requests->find('all', array(
'conditions' => array(
'OR' => array(
$searcharray
)
)
));
It didnt work maybe of the keys in the array, because i set after the $searcharray for example [1] and then it works. I dont want to write the condition as string, but how can i solve it?
You have nested the conditions one level too deep.
Your $searcharray is already nested correctly, if you nest it again as in your example, then you're basically creating an OR node with only one child (which in turn has children itself), which is interpreted as basically "nothing", as you need at least two children for an operator to be used. The children in the array nested one level deeper will then be interpreted as AND, as that is the default when no operator is specified.
Long story short, just pass $searcharray as is:
'conditions' => [
'OR' => $searcharray,
]
See also
Cookbook > Database Access & ORM > Query Builder > Advanced Conditions
I'm looking for a way to have the results of a query that uses the Containable behavior to be formatted the same way as find('list') results are. E.g.:
$this->ModelA->find('all', array(
'contain' => array(
'ModelB' => array(
'ModelC' => array(
// This does NOT work but I need ModelC's fields to be formatted as an associative array where IDs are keys and names are values
'fields' => array('id' => 'name')
)
)
)
));
NOTE: Setting recursive to 1 or 2 instead of using Containable is not an option unless there's no available solution with Containable.
I'm not sure you can get the returned contained data back in the format you want, but you can alter it after finding it. The way Cake actually builds the return from find('list') is using Hash::combine(). So you can alter the returned data using this to make the data look list a find('list') return:-
$data = [
[
'id' => 1,
'name' => 'Foo'
],
[
'id' => 2,
'name' => 'Bar'
]
];
$results = Hash::combine($data, '{n}.id', '{n}.name');
This would return:-
[
1 => 'Foo',
2 => 'Bar'
]
Not sure exactly what your find('all') data looks like as you've not supplied the associations, but guess you can do something like this:-
foreach ($data as &$row) {
$row['ModelB']['ModelC'] = Hash::combine(
$row['ModelB']['ModelC'],
'{n}.id',
'{n}.name'
);
}
$this->ModelA->Behaviors->load('Containable');
$this->ModelA->find('all', array(
'contain' => array( 'ModelB' ,'ModelC'=>array( 'fields' => array('id', 'name'))
)
)
);
Please make sure you have created association of model
I can't figure out for the life of my to select from a collection with the or parameter. It's not working at all for me and I can't really find any documentation on it for php.
Here is my example code that doesn't return anything even though they exist in the collection:
$cursor = $products->find(
array(
'$or' => array(
"brand" => "anti-clothes",
"allSizes" => "small"
)
)
);
The $or operator lets you use boolean or in a query.
You give $or an array of expressions, any of which can satisfy the query.
You provided only one element in the array. Use:
find(array('$or' => array(
array("brand" => "anti-clothes"),
array("allSizes" => "small")
)));
I've been playing around with Mongo for about a week now and I still can't work out how to modify nested arrays in Mongo with php.
So here is a sample document...
array (
'_id' => new MongoId("4cb30f560107ae9813000000"),
'email' => 'mo#maurice-campobasso.com',
'firstname' => 'Maurice',
'lastname' => 'Campobasso',
'password' => 'GOD',
'productions' =>
array (
0 =>
array (
'title' => 'a',
'date' => '1286811330.899',
),
1 =>
array (
'title' => 'b',
'date' => '1286811341.183',
),
2 =>
array (
'title' => 'c',
'date' => '1286811350.267',
),
3 =>
array (
'title' => 'd',
'date' => '1286811356.05',
),
),
)
What I wan't to do is delete an array inside the productions array, but I can't work out how. I've been playing with 'update('$pull' => ...etc)' but I haven't been able to make it work.
OK, there are a few ways to do this. In your case, I would do something like
mymongoobject.update( $unset : { "productions.2" : 1 } }
That's basically saying to unset the ".2" element of productions. Some docs here.
Now $pull should also work, but it's a little tougher because "productions" is actually an array of arrays (or objects with sub-objects). So you'd have to match arrays exactly:
mymongoobject.update( $pull : { "productions" : {'title':'d', 'date':'1286811356.05'} }
In the case above, the unset is probably the easiest option (though it will leave a "hole" in the array)
That is actually very easy, unlike traditional sql stuff you just modify the whole data and pass it back.
$cursor = $mongo->yourDB->yourCollection->findOne("_id",4cb30f560107ae9813000000);
//let's remove last item on productions
array_splice($cursor["productions"],2);
//and update the mongo document
echo $mongo->yourDB->yourCollection->update($cursor);
//it echoes 1 if successful
hope it helps.
I'm probably missing something simple here but I can't seem to find a way to build a query that will allow me to update a match in a group of nested values.
I have a document like this for a blog app I've been working on (currently uses MySQL):
array (
'_id' => new MongoId("4bc8dcee8ba936a8101a0000"),
'created' => '20100418-201312 +0000',
'post-title' => 'Some Post Title',
'post-body' => 'Blah Blah Blah Blah.',
'post-blog-name' => 'default',
'post-comments' =>
array (
0 =>
array (
'comment-title' => 'Test1',
'comment-body' => 'asdf1',
'created' => '20100418-214512 +0000',
'owner' => 'User1',
),
1 =>
array (
'comment-title' => 'Test2',
'comment-body' => 'asdf2',
'created' => '20100418-214512 +0000',
'owner' => 'User2',
),
),
'owner' => 'zach',
'updated' => '20100418-201312 +0000',
)
I'd like to be able to build a query that can search 'comment-title' for a match and then allow me to update/change/delete data as needed.
Obviously I can perform an update using a query which includes the key value. Something like this works:
$collection->update(
array("post-comments.0.comment-title" => $_POST['comment-title']),
array('$set' => array('entries.0' => array('comment-title' => $_POST['comment-title'], 'comment-body' => $_POST['comment-body'], 'owner' => $_SESSION['username'], 'updated' => gmdate('Ymd\-His O')))));
But I expect I'm missing something that would allow me to leave out the key and still be able to match one of the nested arrays based on a value (in this example the 'comment-title').
Anyway, sorry, this probably isn't the best example and I probably will end up using the keys in comments to identify them (comment #) but since nesting and creating rather complex objects seem to be a few of Mongodbs strong points I'm just hoping someone can point out what it is I might be missing.
A query to remove or update all comments by a specific user (say a user the blog author just black-listed) might be a better example. I'm not sure how I'd do this short of pulling out the entire document and then iterating through the nested arrays using PHP.
try ... notice I removed the "key"
$collection->update(array("post-comments.comment-title" ...
Cheers!