PHP MongoDB find with multiple "AND" conditions? - php

After hours of experimentations and readings, I cannot find a solution to this problem:
I want to do a MongoDB->find($query) with multiple AND conditions.
For instance, say I want id = 5 and a < 6 and a > 2 and b > 10 and b < 20
I was expecting $query to be:
$query = array("id" => 5,
"a" => array('$gt' => 2,
'$lt' => 6),
"b" => array('$gt' => 10,
'$lt' => 20))
But this returns empty results with my DB
I tried various syntaxes such as:
$query = array("id" => 5,
array( "a" => array('$gt' => 2,
'$lt' => 6),
"b" => array('$gt' => 10,
'$lt' => 20)))
But this fails too.
Also tried with "$AND" variants, no luck.
Is it possible to "mix" several AND conditions in PHP-MongoDB find() requests?

I've just tested this using MongoDB PHP driver v1.6.11 (PHP-5.5.9). The test data are as below
db.collection.insert({id:5, a:4, b:15})
db.collection.insert({id:9, a:4, b:15})
db.collection.insert({id:5, a:4, b:20})
Using PHP code snippet:
$condition = array(
'$and' => array(
array(
"id" => 5,
"a" => array('$gt' => 2, '$lt' => 6),
"b" => array('$gt' => 10, '$lt' => 20)
)
)
);
$docs = $coll->find($condition);
foreach( $docs as $o=> $doc) {
echo json_encode($doc);
}
The above returns only the first document sample. This indicates that $and should work as expected. I've also tested without $and, i.e. :
$condition = array(
"id" => 5,
"a" => array('$gt' => 2, '$lt' => 6),
"b" => array('$gt' => 10, '$lt' => 20)
);
Which also works the same. Try checking your dataset, whether there is a document matching your criteria.

This issue is closed: bad value types in the DB (string instead of float/double). Works as expected when updating to correct types in DB.

Related

How to declare/define an associative array properly in PHP?

I wrote a program to define an associative array titled $aFilter and tried to print it but I'm not able to. I tried two ways to achieve this but couldn't succeed. Following are the two ways I tried.
Way 1:
<!DOCTYPE html>
<html>
<body>
<?php
$aFilter = Array
(
['pages'] => 1,
['photo'] => 1,
['link'] => 1,
['event'] => 1,
['friend'] => 1,
['user_status'] => 1,
['poll'] => 1,
['quiz'] => 1,
['market'] => 1,
['apps'] => 1
)
print_r($aFilter);
?>
</body>
</html>
Way 2:
<!DOCTYPE html>
<html>
<body>
<?php
$aFilter = Array
(
['pages'] => 1
['photo'] => 1
['link'] => 1
['event'] => 1
['friend'] => 1
['user_status'] => 1
['poll'] => 1
['quiz'] => 1
['market'] => 1
['apps'] => 1
)
print_r($aFilter);
?>
</body>
</html>
After executing both of the above codes I'm getting blank white screen. No any error or warning. Why so happens? How can I get errors and warnings displayed on my webpage without making any change to php.ini file settings?
Can someone please correct the mistake I'm making and help me?
You forgot an ; after defining the array.
And also don't use [] when defining an array. More info on array's.
$aFilter = Array(
'pages' => 1,
'photo' => 1,
'link' => 1,
'event' => 1,
'friend' => 1,
'user_status' => 1,
'poll' => 1,
'quiz' => 1,
'market' => 1,
'apps' => 1
);
print_r($aFilter);
print_r() displays information about a variable in a way that's readable by humans.
It is not the code you need to write.
Both ways are missing the ; after the array definition and Way 2 is missing ,s after each array element. Also, both ways should use 'elName' => 'elValue', instead of ['elName'] => 'elValue',
The problem are:-
Forgot an ; after defining the array.
When you hard-coded value you need to put indexes without brackets.
So write in this way:-
$aFilter = Array(
'pages' => 1,
'photo' => 1,
'link' => 1,
'event' => 1,
'friend' => 1,
'user_status' => 1,
'poll' => 1,
'quiz' => 1,
'market' => 1,
'apps' => 1
);
print_r($aFilter);

mongodb: update nested document by an array?

I have a deeply nested PHP array which I saved as a document in Mongo and ended up with this structure:
{
"_id" : "...",
"categ1" : {
"aaa" : 112.6736,
"bbb" : 83.9137,
"ccc" : 80.3322,
.....
},
"categ2" : {
"xxx" : 1,
"yyy" : 22,
"zzz" : 7,
"subcateg" : {
"sub1" : 1,
"sub2" : 22
}
}
}
Now, I have another array with a similar structure and I would like to increase the values of the record, by the values of the modifier array:
$modifier=array(
'categ1' => array(
'aaa' => 3,
'bbb' => -1,
'mmm' => 11
),
'categ2' => array(
'yyy' => -2,
'subcateg' => array(
'sub1' => -1
)
)
);
How can I increase the values inside the document by the values of the $modifier all at once, in a single query, and without loading the entire document ?
I've looked around the web but couldn't find any info on this.
Also, i'm pretty newbie at Mongo. Thanks
You can get your $modifier array to look like this:
$modifier = array(
'categ1.aaa' => 3,
'categ1.bbb' => -1,
'categ1.mmm' => 11,
'categ2.yyy' => -2,
'categ2.subcateg.sub1' => -1
)
Link for how to get that.
Then you should be able to simply use:
$col->update(
array("_id" => "..."),
array('$inc' => $modifier),
array("upsert" => true)
);

Pull count of records in a table that have the same value with Codeigniter Active Record

I am working on a site where I have a table with "catches" (people have caught fish with a particular lure). The lure_used category is an integer.
I want to find the users "best lure". So i want to loop through all the user_catches rows and return an array that has each lure and how many times it was used.
So for example we might have
catch_1 | lure_used = 5,
catch_2 | lure_used = 3,
catch_3 | lure_used = 6,
catch_4 | lure_used = 3,
so from that i would like to know that 5 and 6 occur 1 time while 3 occurs twice. Therefore 3 is the most successful lure.
I know that I could probably use "MAX" in mysql queries, but i'm not really farmiliar with it and attempts have failed.
I have been able to create an array of lures used like:
$lures = array(5, 3, 6, 3);
So maybe i could just loop through that and output something like...
5 = 1, 3 = 2, 6 = 1.
I guess i'm grasping at straws haha, anyone have a better idea on how to get this done?
Here are all the fields in the "user_catches" table:
'id' => $row->id,
'user_id' => $row->user_id,
'species' => $row->species,
'season' => $row->season,
'lure_used' => $row->lure_used,
'depth' => $row->depth,
'exact_depth' => $row->exact_depth,
'presentation' => $row->presentation,
'catch_weight' => $row->catch_weight,
'length' => $row->length,
'fishing_from' => $row->fishing_from,
'moon_phase' => $row->moon_phase,
'water_temp' => $row->water_temp,
'water_quality' => $row->water_quality,
'notes' => $row->notes,
'rod' => $row->rod,
'reel' => $row->reel,
'line' => $row->line,
'rig' => $row->rig,
'catch_image' => $row->catch_image,
'weather' => $row->weather,
'temp' => $row->temp,
'humidity' => $row->humidity,
'wind' => $row->wind,
'pressure' => $row->pressure,
'visibility' => $row->visibility,
'location' => $row->location,
'weather_icon' => $row->weather_icon,
'catch_date' => $row->catch_date,
SELECT lure, count (*) as count
from user_catches
GROUP BY lures
ORDER BY count;

get integer / float from string in PHP

I ran into an issue with a data feed I need to import where for some reason the feed producer has decided to provide data that should clearly be either INT or FLOAT as strings-- like this:
$CASES_SOLD = "THREE";
$CASES_STOCKED = "FOUR";
Is there a way in PHP to interpret the text string as the actual integer?
EDIT: I should be more clear-- I need to have the $cases_sold etc. as an integer-- so I can then manipulate them as digits, store in database as INT, etc.
Use an associative array, for example:
$map = array("ONE" => 1, "TWO" => 2, "THREE" => 3, "FOUR" => 4);
$CASES_SOLD = $map["THREE"]; // 3
If you are only interested by "converting" one to nine, you may use the following code:
$convert = array('one' => 1,
'two' => 2,
'three' => 3,
'four' => 4,
'five' => 5,
'six' => 6,
'seven' => 7,
'eight' => 8,
'nine' => 9
);
echo $convert[strtolower($CASES_SOLD)]; // will display 3
If you only need the base 10 numerals, just make a map
$numberMap = array(
'ONE' => 1
, 'TWO' => 2
, 'THREE' => 3
// etc..
);
$number = $numberMap[$CASES_SOLD];
// $number == 3'
If you need something more complex, like interpreting Four Thousand Two Hundred Fifty Eight into 4258 then you'll need to roll up your sleeves and look at this related question.
Impress your fellow programmers by handling this in a totally obtuse way:
<?php
$text = 'four';
if(ereg("[[.$text.]]", "0123456789", $m)) {
$value = (int) $m[0];
echo $value;
}
?>
You need a list of numbers in english and then replace to string, but, you should play with 'thousand' and 'million' clause where must check if after string 'thousend-three' and remove integer from string.
You should play with this function and try change if-else and add some functionality for good conversion:
I'm writing now a simple code for basic, but you know others what should change, play!
Look at million, thousand and string AND, it should be change if no in string like '1345'. Than replace with str_replace each of them separaterly and join them to integer.
function conv($string)
{
$conv = array(
'ONE' => 1,
'TWO' => 2,
'THREE' => 3,
'FOUR' => 4,
'FIVE' => 5,
'SIX' => 6,
'SEVEN' => 7,
'EIGHT' => 8,
'NINE' => 9,
'TEN' => 10,
'ELEVEN' => 11,
'TWELVE' => 12,
'THIRTEEN' => 13,
'FOURTEEN' => 14,
'FIFTEEN' => 15,
'SIXTEEN' => 16,
'SEVENTEEN' => 17,
'EIGHTEEN' => 18,
'NINETEEN' => 19,
'TWENTY' => 20,
'THIRTY' => 30,
'FORTY' => 40,
'FIFTY' => 50,
'SIXTY' => 60,
'SEVENTY' => 70,
'EIGTHY' => 80,
'NINETY' => 90,
'HUNDRED' => 00,
'AND' => '',
'THOUSAND' => 000
'MILLION' => 000000,
);
if (stristr('-', $string))
{
$val = explode('-', $string);
#hardcode some programming logic for checkers if thousands, should if trim zero or not, check if another values
foreach ($conv as $conv_k => $conv_v)
{
$string[] = str_replace($conv_k, $conv_v, $string);
}
return join($string);
}
else
{
foreach ($conv as $conv_k => $conv_v)
{
$string[] = str_replace($conv_k, $conv_v, $string);
}
return join($string);
}
}
Basically what you want is to write a parser for the formal grammar that represents written numbers (up to some finite upper bound). Depending on how high you need to go, the parser could be as trivial as
$numbers = ('zero', 'one', 'two', 'three');
$input = 'TWO';
$result = array_search(strtolower($input), $numbers);
...or as involved as a full-blown parser generated by a tool as ANTLR. Since you probably only need to process relatively small numbers, the most practical solution might be to manually hand-code a small parser. You can take a look here for the ready-made grammar and implement it in PHP.
This is similar to Converting words to numbers in PHP
PHP doesn't have built in conversion functionality. You'd have to build your own logic based on switch statements or otherwise.
Or use an existing library like:
http://www.phpclasses.org/package/7082-PHP-Convert-a-string-of-English-words-to-numbers.html

Mongodb query from php - can't getting it working

Trying to do a simple mongodb query that drives me mad.... I have the following table/db:
[_id] => MongoId Object (
[$id] => 4f22efa1ef9dec8495b374bc
)
[h1] => a
[h2] => b
[h3] => c
[_id] => MongoId Object (
[$id] => 4f22efa1ef9dec8495b374bd
)
[h1] => d
[h2] => e
[h3] => f
Using the mongo tool command line and typing:
db.things.find({$or: [{'h1' : 'a'},{'h1': 'd'}]})
I get:
{ "_id" : ObjectId("4f22efa1ef9dec8495b374bc"), "h1" : "a", "h2" : "b", "h3" : "c" }
{ "_id" : ObjectId("4f22efa1ef9dec8495b374bd"), "h1" : "d", "h2" : "e", "h3" : "f" }
Which is fine. However trying doing the same from PHP, I get nothing ??:
$m = new Mongo();
$db = $m->selectDB('testdb');
$collection = new MongoCollection($db, 'things');
$query = array( '$or' => array( array('h1' => 'a')),
array('h1' => 'd'));
$cursor = $collection->find($query);
I do not see what I am doing wrong, but I have tried anything (or I think so) for 3 days now and it will not work. If I do queries using '>=' '<=' '<>' '<' '>' it works fine but using '=' as in this case it does not.
Thanks for your effort !
You're better off using $in for your given example, i.e.:
$collection->find(array('h1' => array('$in' => array('a', 'd'))));
As to why your query doesn't work - you're not using $or correctly (or infact, at all). This is the query you've put in the question reformatted:
$query = array(
'$or' => array(
array('h1' => 'a')
),
array('h1' => 'd')
);
Whereas you would need:
$query = array(
'$or' => array(
array('h1' => 'a'),
array('h1' => 'd')
)
);
If you have a look in the mongodb error log most likely it says something about that illegal loose top-level array in the conditions.

Categories