Encoding data into JSON object in php - php

I have to send the JSON in the following format:
{
"suomottoRegVO" : {
"rgdtls" : {
"aplty" : APLSM
},
"docls" : [
{
"id" : 123,
"ty" : 101,
},
{
"id" : 123,
"ty" : 101,
}
],
"todtls":{
"tonm":"Gaurav Kumar",
"todg":"Tax Official",
"pl":"Bangalore",
"dt":" 12-04-2015 23:05:23"
}
}
}
I am using the following code to encode it into JSON and since docls is an array, I am using a loop to put two values into it.
$json_string = array(
'suomottoRegVO' => array (
'rgdtls'=> array(
'aplty'=>'APLSM',
),
'todtls' => array(
'tonm' => 'Gaurav Kumar',
'todg' => 'Tax Official',
'pl' => 'Bangalore',
'dt' => ' 12-04-2015 23:05:23',
)
)
);
for ($i=0; $i<2; $i++) {
$docls[] = array (
'id' => '123',
'ty' => '101'
);
}
$json_string['docls']=$docls;
json_encode($json_string);
When I print the JSON, it becomes:
{
"suomottoRegVO" : {
"rgdtls" : {
"aplty" : APLSM
},
"todtls":{
"tonm":"Gaurav Kumar",
"todg":"Tax Official",
"pl":"Bangalore",
"dt":" 12-04-2015 23:05:23"
}
}
"docls" : [
{
"id" : 123,
"ty" : 101,
},
{
"id" : 123,
"ty" : 101,
}
],
}
The "docls" should be inside "suomottoRegVO" but is not. Please anyone guide me to solve this.

Try this...
You need to paas your array under $json_string['suomottoRegVO'] so try this way...
$json_string['suomottoRegVO']['docls']=$docls;
json_encode($json_string);

Related

How to find the average rating based on item name

I am working on building simple recommendation engine using PHP and MongoDB. I am trying to find the average rating of each item but I did not figure it out yet.
my collection is:
{
"_id" : 1,
"item" : "efg",
"rating" : 5.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 2,
"item" : "efg",
"rating" : 2.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 3,
"item" : "abc",
"rating" : 5.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 4,
"item" : "abc",
"rating" : 4.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
{
"_id" : 5,
"item" : "xyz",
"rating" : 3.0,
"date" : ISODate("2014-01-01T08:00:00.000Z")
}
This is the code I have tried recently:
$out = $sales->aggregate(
array(
'$group' => array(
'_id' => '$item',
'avgrating' => array('$avg' => '$rating')
)
)
);
var_dump($out);
Please try executing following code snippet
$out = $sales->aggregate(
array(
'$group' => array(
'_id' => array('item' => '$item'),
'avgrating' => array('$avg' => '$rating')
)
)
);
var_dump($out);
I got it working using this code:
$pipeline = array(
array(
'$group' => array(
'_id' => '$itemId',
'avgrating' => array('$avg' => '$rating'),
),
)
);
$out = $sales1->aggregate($pipeline);
var_dump($out)

MongoDB query convert in to PHP?

I am having trouble converting it to PHP. My query is working in mongodb and get output well. But same query i tried to convert into php shown error
Array
(
[ok] => 0
[errmsg] => A pipeline stage specification object must contain exactly one field.
[code] => 16435
)
My collection sample as follows
{
"_id" : ObjectId("5790f9407ffbe031fa2049e3"),
"EventTS" : ISODate("2016-07-01T04:30:00.000+0530"),
"KeyValues" : [
{
"InputVolt" : null
},
{
"InputVolt" : 250
},
{
"InputVolt" : 230
},
{
"InputVolt" : 230
},
{
"InputVolt" : 240
}
]
},
{
"_id" : ObjectId("5790f9407ffbe031fa2049e4"),
"EventTS" : ISODate("2016-07-01T04:35:00.000+0530"),
"KeyValues" : [
{
"InputVolt" : null
},
{
"InputVolt" : 260
},
{
"InputVolt" : null
},
{
"InputVolt" : null
},
{
"InputVolt" : null
}
]
}
My mongodb query is
db.sample_coll.aggregate(
{
$unwind: {
path:"$KeyValues",
includeArrayIndex:"arrayIndex",
preserveNullAndEmptyArrays:true
}
},
{
$project: {
timestamp:{
"$add":["$EventTS",{"$multiply":[60000,"$arrayIndex"]}]
} ,
"InputVolt":"$KeyValues.InputVolt",
arrayIndex:1
}
},
{
$match: {
$and: [
{InputVolt: {$ne: null}}
]
}
}
);
My mongo query convert into php as follows
$pipeline = array(
array('$unwind' =>
array( 'path' => '$KeyValues'),
array( 'includeArrayIndex' => 'arrayIndex' ),
array( 'preserveNullAndEmptyArrays' => 'true' )
),
array(
'$project' => array(
'timestamp' => array(
'$add' => array(
'$EventTS',
array('$multiply' => array( 60000, '$arrayIndex' ))
)
),
array( 'InputVolt' => array( '$KeyValues', 'InputVolt' ) ) ,
array('arrayIndex' => 1)
)
),
array(
'$match' => array(
'$and' => array(
array('InputVolt' => array('$ne' => null )),
)
)
)
);
$result = $collection->aggregate($pipeline);
I don't know what happen. Please suggest me.

Nested json string with variables in php

I will not lie to you guys: i hate nested Arrays.
So instead of my [working] code below
$query_array = Array(
"fields" => Array ("timestamp", "user.raw", "mailbox", "verb", "backend"),
"size" => 1,
"sort" => Array (Array ("#timestamp" => Array ("order" => $varOrder))),
"query" => Array (
"bool" => Array (
"must" => Array (
Array ("match" => Array ("verb" => "open")),
Array ("term" => Array ($varField => $varValue))
)
)
)
);
I want to use the [non working] code below
$query_json_string = '{
"fields" : [ "timestamp", "user.raw", "mailbox", "verb", "backend" ],
"size" : 1,
"sort" : [ { "#timestamp" : { "order" : $varOrder } } ],
"query" : {
"bool": {
"must": [
{ "match" : { "verb" : "open" } },
{ "term" : { $varField : $varValue } }
]
}
}
}';
So much easier to maintain...
But inside the single quotes the variables varOrder, varField and varValue are never expanded (i believe).
How can i use variables inside this nice and clean json string?
As I understand your question, you're simply not happy with php's array syntax. If that's the case, then don't use the old syntax. Instead use simple square brackets, which are available since version 5.4.
Doing so, your final code could be:
$query = [
"fields" => ["timestamp", "user.raw", "mailbox", "verb", "backend"],
"size" => 1,
"sort" => [["#timestamp" => ["order" => $varOrder]]],
"query" => [
"bool" => [
"must" => [
["match" => ["verb" => "open"]],
["term" => [$varField => $varValue]]
]
]
]
];
Which issn't far off your desired syntax. The only difference being => instead of :. But with the added benefit of not needing to declare objects with {}.
JSON is basically Javascript's version of a associative array.
$query_array = Array(
"fields" => Array ("timestamp", "user.raw", "mailbox", "verb", "backend"),
"size" => 1,
"sort" => Array (Array ("#timestamp" => Array ("order" => $varOrder))),
"query" => Array (
"bool" => Array (
"must" => Array (
Array ("match" => Array ("verb" => "open")),
Array ("term" => Array ($varField => $varValue))
)
)
)
);
$query_json_string = json_encode($query_array);
But if you have a problem with that, heredoc syntax should work for you..
$query_json_string = <<<JSON
{
"fields" : [ "timestamp", "user.raw", "mailbox", "verb", "backend" ],
"size" : 1,
"sort" : [ { "#timestamp" : { "order" : $varOrder } } ],
"query" : {
"bool": {
"must": [
{ "match" : { "verb" : "open" } },
{ "term" : { $varField : $varValue } }
]
}
}
}
JSON;
// if you wanted PHP array,
$query_array = json_decode($query_json_string, true);
You can switch the from single to double quotes and escape your double qoutes
$query_json_string = "{
\"fields\" : [ \"timestamp\", \"user.raw\", \"mailbox\", \"verb\", \"backend\" ],
\"size\" : 1,
\"sort\" : [ { \"#timestamp\" : { \"order\" : $varOrder } } ],
\"query\" : {
\"bool\": {
\"must\": [
{ \"match\" : { \"verb\" : \"open\" } },
{ \"term\" : { $varField : $varValue } }
]
}
}
}";

mongodb avg in aggregation of array element

I have the following collection structure
{
"_id": {
"d_timestamp": NumberLong(1429949699),
"d_isostamp": ISODate("2015-04-25T08:14:59.0Z")
},
"XBT-USD-cpx-okc": [
{
"buySpread": -1.80081
}
I run the following aggregation
$spreadName ='XBT-USD-stp-nex';
$pipe = array(
array(
'$match' => array(
'_id.d_isostamp' => array(
'$gt' => $start, '$lt' => $end
)
)
),
array(
'$project' => array(
'sellSpread' =>'$'.$spreadName.'.sellSpread',
)
),
array(
'$group' => array(
'_id' => array(
'isodate' => array(
'$minute' => '$_id.d_isostamp'
)
),
'rsell_spread' => array(
'$avg' => '$sellSpread'
),
)
),
);
$out = $collection->aggregate($pipe ,$options);
and I get as a result the value 0 for rsell_spread whereas if I run a $max for instance instead of an $avg in the $group , I get an accurate value for rsell_spread , w/ the following structure
{
"_id": {
"isodate": ISODate("2015-04-25T08:00:58.0Z")
},
"rsell_spread": [
-4.49996▼
]
}
So I have two questions :
1/ How come does the $avg function does not work?
2/ How can I can a result not in an array when I use $max for example (just a regular number)?
The $avg group accumulator operator does work, it's only that in your case it is being applied to an element in an array and thus gives the "incorrect" result.
When you use the $max group accumulator operator, it returns the the highest value that results from applying an expression to each document in a group of documents, thus in your example it returned the maximum array.
To demonstrate this, consider adding a few sample documents to a test collection in mongoshell:
db.test.insert([
{
"_id" : {
"d_timestamp" : NumberLong(1429949699),
"d_isostamp" : ISODate("2015-04-25T08:14:59.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80081
}
]
},
{
"_id" : {
"d_timestamp" : NumberLong(1429949710),
"d_isostamp" : ISODate("2015-04-25T08:15:10.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80079
}
]
},
{
"_id" : {
"d_timestamp" : NumberLong(1429949720),
"d_isostamp" : ISODate("2015-04-25T08:15:20.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80083
}
]
},
{
"_id" : {
"d_timestamp" : NumberLong(1429949730),
"d_isostamp" : ISODate("2015-04-25T08:15:30.000Z")
},
"XBT-USD-stp-nex" : [
{
"sellSpread" : -1.80087
}
]
}
])
Now, replicating the same operation above in mongoshell:
var spreadName = "XBT-USD-stp-nex",
start = new Date(2015, 3, 25),
end = new Date(2015, 3, 26);
db.test.aggregate([
{
"$match": {
"_id.d_isostamp": { "$gte": start, "$lte": end }
}
},
{
"$project": {
"sellSpread": "$"+spreadName+".sellSpread"
}
}/*,<--- deliberately omitted the $unwind stage from the pipeline to replicate the current pipeline
{
"$unwind": "$sellSpread"
}*/,
{
"$group": {
"_id": {
"isodate": { "$minute": "$_id.d_isostamp"}
},
"rsell_spread": {
"$avg": "$sellSpread"
}
}
}
])
Output:
/* 0 */
{
"result" : [
{
"_id" : {
"isodate" : 15
},
"rsell_spread" : 0
},
{
"_id" : {
"isodate" : 14
},
"rsell_spread" : 0
}
],
"ok" : 1
}
The solution is to include an $unwind operator pipeline stage after the $project step, this will deconstruct the XBT-USD-stp-nex array field from the input documents and outputs a document for each element. Each output document replaces the array with an element value. This will then make it possible for the $avg group accumulator operator to work.
Including this will give the aggregation result:
/* 0 */
{
"result" : [
{
"_id" : {
"isodate" : 15
},
"rsell_spread" : -1.80083
},
{
"_id" : {
"isodate" : 14
},
"rsell_spread" : -1.80081
}
],
"ok" : 1
}
So your final working aggregation in PHP should be:
$spreadName ='XBT-USD-stp-nex';
$pipe = array(
array(
'$match' => array(
'_id.d_isostamp' => array(
'$gt' => $start, '$lt' => $end
)
)
),
array(
'$project' => array(
'sellSpread' =>'$'.$spreadName.'.sellSpread',
)
),
array('$unwind' => '$sellSpread'),
array(
'$group' => array(
'_id' => array(
'isodate' => array(
'$minute' => '$_id.d_isostamp'
)
),
'rsell_spread' => array(
'$avg' => '$sellSpread'
),
)
),
);
$out = $collection->aggregate($pipe ,$options);

MongoDB aggregate query using PHP driver

I have a working MongoDB aggregate query which I can run via the MongoDB shell. However, I am trying to convert it to work with the official PHP Mongo driver (http://php.net/manual/en/mongocollection.aggregate.php).
Here is the working raw MongoDB query:
db.executions.aggregate( [
{ $project : { day : { $dayOfYear : "$executed" } } },
{ $group : { _id : { day : "$day" }, n : { $sum : 1 } } } ,
{ $sort : { _id : -1 } } ,
{ $limit : 14 }
] )
Here is my attempt (not working) in PHP using the Mongo driver:
$result = $c->aggregate(array(
'$project' => array(
'day' => array('$dayOfYear' => '$executed')
),
'$group' => array(
'_id' => array('day' => '$day'),
'n' => array('$sum' => 1)
),
'$sort' => array(
'_id' => 1
),
'$limit' => 14
));
The error from the above PHP code is:
{"errmsg":"exception: wrong type for field (pipeline) 3 != 4","code":13111,"ok":0}
Any ideas? Thanks.
The parameter in your Javascript is an array of 4 objects with one element each, in your PHP it's an associative array (object) with 4 elements. This would represent your Javascript:
$result = $c->aggregate(array(
array(
'$project' => array(
'day' => array('$dayOfYear' => '$executed')
),
),
array(
'$group' => array(
'_id' => array('day' => '$day'),
'n' => array('$sum' => 1)
),
),
array(
'$sort' => array(
'_id' => 1
),
),
array(
'$limit' => 14
)
));
In addition, if you have at least PHP5.4, you can use simpler array syntax. Transformation to PHP is then trivial, you simply replace curly braces with square brackets and colons with arrows:
$result = $c->aggregate([
[ '$project' => [ 'day' => ['$dayOfYear' => '$executed'] ] ],
[ '$group' => ['_id' => ['day' => '$day'], 'n' => ['$sum' => 1] ] ],
[ '$sort' => ['_id' => 1] ],
[ '$limit' => 14 ]
]);
You can also use the JSON array directly:
$json = [
'{ $project : { day : { $dayOfYear : "$executed" } } },
{ $group : { _id : { day : "$day" }, n : { $sum : 1 } } } ,
{ $sort : { _id : -1 } } ,
{ $limit : 14 }'
];
$pipeline = [];
foreach ($json as $stage) {
array_push($pipeline, toPHP(fromJSON($stage)));
}
$result = $c->aggregate($pipeline);
You can also use combination like this:
use function MongoDB\BSON\toRelaxedExtendedJSON;
use function MongoDB\BSON\fromPHP;
use function MongoDB\BSON\toPHP;
use function MongoDB\BSON\fromJSON;
$operator = '$dayOfYear';
$json = [];
array_push($json, toRelaxedExtendedJSON(fromPHP(
array('$project ' => array('day' => array($operator => '$executed')))
)));
array_push($json,
'{ $group : { _id : { day : "$day" }, n : { $sum : 1 } } } ,
{ $sort : { _id : -1 } } ,
{ $limit : 14 }'
);
$pipeline = [];
foreach ($json as $stage) {
array_push($pipeline, toPHP(fromJSON($stage)));
}
$result = $c->aggregate($pipeline);
or
$operator = '$dayOfYear';
$json = [];
array_push($json,
'{ $group : { _id : { day : "$day" }, n : { $sum : 1 } } } ,
{ $sort : { _id : -1 } } ,
{ $limit : 14 }'
);
$pipeline = [];
array_push($pipeline, array('$project ' => array('day' => array($operator => '$executed'))));
foreach ($json as $stage) {
array_push($pipeline, toPHP(fromJSON($stage)));
}
$result = $c->aggregate($pipeline);
If your aggregation query is dynamic or based on user-input be aware of NoSQL-Injection!
https://www.acunetix.com/blog/web-security-zone/nosql-injections/

Categories