MongoDB MapReduce (1.2) PHP with parameter - php

I'm trying to 'parameterize' a MongoDB MapReduce on PHP and seem to be hitting a wall. I feel like I'm missing something obvious since I'm not super experienced in PHP or javascript. I can get the map reduce to work and return what I need if I hard code the value I want it to check.
For example
$client = new MongoDB\Client;
$collection = $client->selectCollection('collection','responses');
$map = new MongoDB\BSON\Javascript('function() { if(this.response == "Yes") { emit("matches", 1)}};');
$reduce = new MongoDB\BSON\Javascript('function(key, values) { return Array.sum(values)};');
$out = ['inline' => 1];
$data = $collection->mapReduce($map, $reduce, $out);
foreach ($data as $d) {
var_dump($d);
}
I would like this if(this.response == "Yes") "Yes" value to be a variable so I can filter on other responses.
I've tried a handful of ways and I can't get it to work.
Any tips or ideas?
Thanks!

Related

PHP - What is the best way to access a property of an object which is an array element

I have an object which is an array of JSON objects. Kinda Like this,
$object = [
{
"id":1,
"name":"blue",
"order":4
},
{
"id":2,
"name":"green",
"order":6
},
{
"id":3,
"name":"yellow",
"order":2
}
]
I wanted to access the properties in a simple way and a single line maybe like this,
Say if I wanted the "order" of the object with name "blue"
$blue_order = $object[something]->[name="blue"]->order;
Kinda mixed Jquery in this. But I hope you understand. Right now the best I've got is this,
for($i=0; $i<count($object); $i++){
if($object[$i]->name == "blue"){
$blue_order = $object[$i]->order;
}
}
This seems very inefficient though and I don't want to use a loop because the array is very large and looping through it will be very slow. So how do I do this?
I used a "for" loop instead of foreach because the array can be null. And also the order of the array elements will not always be the same.
So I can't do something like
$object[0]->order
<?php
$arr = array(
array('id'=>1,'name'=>'blue','order'=>4),
array('id'=>2,'name'=>'green','order'=>6),
array('id'=>3,'name'=>'yellow','order'=>2),
);
// $json is JSON version of the arrays in $arr
$json = json_encode($arr);
// show $json
echo $json . "\n";
// create arrays from JSON so it can be used in PHP easier
$obj = json_decode($json);
$color = 'blue';
$blue_order = array_filter($obj, function($i) use ($color) { return $i->name == $color; })[0]->order;
echo "Blue Order: " . $blue_order;
You may be able to use array_filter to help this become a one-liner. I included the json_decode and json_encode so I could have a complete example.
You could still use foreach but check if the array isn't empty first, like this:
if(!empty($object)){
foreach($object as $element){
if($element->name == "blue"){
$blue_order = $element->order;
}
}
}
Also, your code looks efficient to me, what I would probably add is a break after you find the value, like this:
if(!empty($object)){
foreach($object as $element){
if($element->name == "blue"){
$blue_order = $element->order;
break;
}
}
}
If your object has a lot of information and you're going to do a lot of searches, then you could do some pre-processing so it get easier to search, like this:
$object_by_name = array();
if(!empty($object)){
foreach($object as $element){
$object_by_name[$element->name] = $element;
}
}
Then, you could search it like this:
if(!empty($object_by_name['blue'])){
$blue_order = $object_by_name['blue']->order
}
Keep it simple.
You're writing way too much code.
$array_list = ($array_list)?:[];
$array_list = array_filter($array_list,function($var) {
return ($var->name=="blue");
});
$order = ($array_list)? $array_list[0]->order :'';

How to improve the performance of this PHP code?

This is the structure of the php code that I am using
$Objects = $account->api1(); // This returns an object array with each object being O(data1, data2, data3)
$retValue = array();
foreach($Objects as $O)
{
if($O->data2 == 'something')
{
$data4 = $account->api2($O->data2); // returns a value $data4
// Initialize $tmp;
$tmp->data1 = $O->data1;
$tmp->data3 = $O->data3;
$tmp->data4 = $data4;
$retValue[] = $tmp;
}
}
Basically what I need is an object array of the following for which data2 = 'something'
O(data1,data3,data4)
Is there a way in which I can simplify this process. Each api call costs money and also involves request across request which makes this process both costly and also slow.Can this be improved anyway ? Even little bit improvement in performance/no of calls would be really helpful.
Important: I'll assume you have some typos in your question and the following equivalences
$data2 means $O->data2 Fixed in the question
$O->data4 means $data4 Fixed in the question
Calling $account->api2($O->data2) should always return the same value
because you always check that $O->data2 is equal to "something"..
So you can call it just once, insteand of each time you have a hit.
<?php
$Objects = $account->api1(); // This returns an object array with each object being O(data1, data2, data3)
$retValue = array();
foreach($Objects as $O)
{
if($O->data2 == 'something')
{
// Here, you just call api2 the first time (or never, maybe, if you never needed to)
$data4 = isset($data4) ? $data4 : $account->api2($O->data2);
// Initialize $tmp;
$tmp->data1 = $O->data1;
$tmp->data3 = $O->data3;
$tmp->data4 = $data4;
$retValue[] = $tmp;
}
}
?>

Multi-dimensional array search to preserve parent

TL;DR
I have this data: var_export and print_r.
And I need to narrow it down to: http://pastebin.com/EqwgpgAP ($data['Stock Information:'][0][0]);
How would one achieve it? (dynamically)
I'm working with vTiger 5.4.0 CRM and am looking to implement a function that would return a particular field information based on search criteria.
Well, vTiger is pretty weakly written system, looks and feels old, everything comes out from hundreds of tables with multiple joins (that's actually not that bad) etc., but job is job.
The need arose from getting usageunit picklist from Products module, Stock Information block.
Since there is no such function as getField();, I am looking forward to filter it out from Blocks, that is actually gathering the information about fields also.
getBlocks(); then calls something close to getFields();, that again something close to getValues(); and so on.
So...
$focus = new $currentModule(); // Products
$displayView = getView($focus->mode);
$productsBlocks = getBlocks($currentModule, $displayView, $focus->mode, $focus->column_fields); // in theory, $focus->column_fields should/could be narrowed down to my specific field, but vTiger doesn't work that way
echo "<pre>"; print_r($productsBlocks); echo "</pre>"; // = http://pastebin.com/3iTDUUgw (huge dump)
As you can see, the array under the key [Stock Information:], that actually comes out from translations (yada, yada...), under [0][0] contains information for usageunit.
Now, I was trying to array_filter(); the data out from there, but only thing I've managed to get is $productsBlocks stripped down to only contain [Stock Information:] with all the data:
$getUsageUnit = function($value) use (&$getUsageUnit) {
if(is_array($value)) return array_filter($value, $getUsageUnit);
if($value == 'usageunit') return true;
};
$productsUsageUnit = array_filter($productsBlocks, $getUsageUnit);
echo "<pre>"; print_r($productsUsageUnit); echo "</pre>"; // = http://pastebin.com/LU6VRC4h (not that huge of a dump)
And, the result I'm looking forward to is http://pastebin.com/EqwgpgAP, that I've manually got by print_r($productsUsageUnit['Stock Information:'][0][0]);.
How do I achieve this? (dynamically...)
function helper($data, $query) {
$result = array();
$search = function ($data, &$stack) use(&$search, $query) {
foreach ($data as $entry) {
if (is_array($entry) && $search($entry, $stack) || $entry === $query) {
$stack[] = $entry;
return true;
}
}
return false;
};
foreach ($data as $sub) {
$parentStack = array();
if ($search($sub, $parentStack)) {
$result[] = $parentStack[sizeof($parentStack) - 2];
}
}
return $result;
}
$node = helper($data, 'usageunit');
print_r($node);

How to reffer dynamically to a php ARRAY variable(s)?

Everybody knows that you can access a variable in PHP using this: ${'varName'}. But when you need to get/set a variable witch is part of an array, why doesn't it work ? Suppose we have this piece of code:
<?php
$myArray = array(...);
$myVarName = "myArray['my1']['my11']['my111']";
${$myVarName} = "new value";
?>
Shouldn't it work ?
I have tested it again and again - it is not working..
Is it there a way to do that?
I recommend you not to use dynamic variables like ${$var}.
What you want is modifying a multi-dimensional associative array according to a path of keys.
<?php
$myArray = array(...); // multi-dimensional array
$myVarPath = array('my1', 'my11', 'my111');
setValueFromPath($myArray, $myVarPath);
function getValueFromPath($arr, $path)
{
// todo: add checks on $path
$dest = $arr;
$finalKey = array_pop($path);
foreach ($path as $key) {
$dest = $dest[$key];
}
return $dest[$finalKey];
}
function setValueFromPath(&$arr, $path, $value)
{
// we need references as we will modify the first parameter
$dest = &$arr;
$finalKey = array_pop($path);
foreach ($path as $key) {
$dest = &$dest[$key];
}
$dest[$finalKey] = $value;
}
This is a procedural example to keep it simple. You may want to put your hierarchical array and this functions inside a class.
Shouldn't it work ?
No.
Everybody knows that you can access a variable in PHP using this: ${'varName'}.
Yes. Yet everybody knows that's lame.
How to refer dynamically to a php array variable(s)?
having array of ('my1','my11','my111') you can refer to any particular array member using merely a loop.
You could do something like this, but it would be a really bad idea. Sorry Col. ;)
<?php
$mA = array();
$mVN = "mA['m1']['m2']['m3']";
eval('$'. $mVN . ' = "new value";');
print_r($mA);
?>

Twitter API JSON Help

I've been trying to play with the Twitter API a bit and this is what I have so far:
function get_twitter_user_data($user_id, $limit = 3)
{
$twitter_username = 'twitter';
$twitter_json = #file_get_contents('http://api.twitter.com/1/statuses/user_timeline.json?&include_rts=1&screen_name='.$twitter_username.'&count='.$limit);
$twitter_data = json_decode($twitter_json);
if ( ! $twitter_data) {
return array();
}
foreach ($twitter_data[0]->user as $user) {
$image = $user->profile_image_url;
}
// doesn't do anything
echo $image.'<br/><br/>';
// works
echo $twitter_data[0]->user->profile_image_url;
}
Been trying to figure this out far too long. And yes, I've done research but the solutions that I've found have no worked for me. I think maybe I'm just extremely tired and can't see the issue right now.
Anybody mind explaining why looping through $twitter_data doesn't work but output a direct value with $twitter_data[0]->user->profile_image_url does?
Many thanks.
You have to do this instead:
foreach ($twitter_data as $status) {
$user = $status->user;
foreach ($twitter_data[0]->user as $user) iterates over the values of the poster of the first status.

Categories