It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I have a multiple time series in a MySQL database that I am fetching with PHP
(fetch_assoc) .
Each series has the same X axis but different Y axes.
X axis: datetime (POSIX values).
Y axes:
air_temperature
dew_point_temperature
sea_level_pressure
wind_direction
wind_speed_rate
sky_condition_total_coverage_code
liquid_precipitation_depth_dimension_one_hr
liquid_precipitation_depth_dimension_six_hr
I need to output this data in a specific JSON structure.
Here is an example of the proper end result:
{ "firstRow" : { "beginTime" : "2012-10-09 00:00:01",
"endTime" : "2012-10-10 00:00:00",
"tMax" : "56.0",
"tMean" : "52.5",
"tMin" : "49.0"
},
"interval" : "daily",
"lastRow" : { "beginTime" : "2012-10-15 00:00:01",
"endTime" : "2012-10-16 00:00:00",
"tMax" : "72.0",
"tMean" : "64.0",
"tMin" : "56.0"
},
"series" : [ { "color" : "#FFAE28",
"data" : [ [ 1349740801000,
56
],
[ 1349827201000,
60
],
[ 1349913601000,
69
],
[ 1350000001000,
61
],
[ 1350086401000,
57
],
[ 1350172801000,
56
],
[ 1350259201000,
72
]
],
"name" : "Maximum Temperature (ºF)",
"type" : "spline",
"yAxis" : 0,
"zIndex" : 100
},
{ "color" : "#4bf827",
"data" : [ [ 1349740801000,
52.5
],
[ 1349827201000,
56
],
[ 1349913601000,
59
],
[ 1350000001000,
55.5
],
[ 1350086401000,
49.5
],
[ 1350172801000,
49.5
],
[ 1350259201000,
64
]
],
"name" : "Mean Temperature (ºF)",
"type" : "spline",
"yAxis" : 0,
"zIndex" : 100
},
{ "color" : "#2dc1f0",
"data" : [ [ 1349740801000,
49
],
[ 1349827201000,
52
],
[ 1349913601000,
49
],
[ 1350000001000,
50
],
[ 1350086401000,
42
],
[ 1350172801000,
43
],
[ 1350259201000,
56
]
],
"name" : "Minimum Temperature (ºF)",
"type" : "spline",
"yAxis" : 0,
"zIndex" : 100
}
],
"title" : "New York Laguardia Arpt: Daily Temperature",
"xAxis" : { "max" : 1350259201000,
"maxZoom" : 604800000,
"min" : 1349740801000
},
"yAxis" : { "endOnTick" : false,
"gridLineColor" : "#777",
"gridLineWidth" : 1,
"labels" : { "enabled" : true,
"style" : { "color" : "#eee" }
},
"lineWidth" : 0,
"max" : null,
"maxPadding" : 0,
"min" : null,
"opposite" : false,
"startOnTick" : true,
"tickInterval" : null,
"title" : { "style" : { "color" : "#eee" },
"text" : "Degrees (Fahrenheit)"
}
}
}
Some help with this would be appreciated!
You need to get the data from the database into a php array with the same structure as the javascript representation you want. Then you can use json_encode($arr_data) to create the javascript representation.
In other words, your $arr_data must end up similar to this:
$arr_data = array(
"firstRow" => array(
"beginTime" => "2012-10-09 00:00:01",
"endTime" => "2012-10-10 00:00:00",
"tMax" => "56.0",
"tMean" => "52.5",
"tMin" => "49.0"
),
"interval" => "daily",
"lastRow" => array(
"beginTime" => "2012-10-15 00:00:01",
"endTime" => "2012-10-16 00:00:00",
"tMax" => "72.0",
"tMean" => "64.0",
"tMin" => "56.0"
),
"series" => array(
array(
"color" => "#FFAE28",
"data" => array(
array(1349740801000, 56),
array(1349827201000, 60),
etc...
),
"name" => "Maximum Temperature (ºF)",
"type" => "spline",
etc....
)
)
);
So, you must write a loop to create this php array, maybe something like this (depending on your db fields):
if ($result = $mysqli->query($query)) {
$arr_data = array();
$i = 0;
while ($row = $result->fetch_assoc()) {
$arr_firstRow = array();
$arr_firstRow["beginTime"] = $row["beginTime"];
$arr_firstRow["endTime"] = $row["endTime"];
etc...
$arr_data[$i]["firstRow"] = $arr_firstRow;
$arr_data[$i]["interval"] = $row["interval"];
etc...
$i++;
}
}
And then, you can use json_encode($arr_data).
Have a look at json_encode/json_decode as it will do what you're looking for.
Translation:
JSON=>PHP
json_decode the data and PHP will create the structure using the same outline.
PHP=>JSON
Create the structure using PHP objects then call json_encode to output the information.
If some manipulation needs to be done before you can encode it, you'll have to do it. Judging by the wording of your question the database isn't a direct 1-to-1 translation to JSON (so you'll need to use the data to create the structure first, then pass that structure to the encoder).
Related
This question already has answers here:
How to Update Multiple Array Elements in mongodb
(16 answers)
Closed 3 years ago.
I want to update many documents on my db but are nested arrays so I need to use arrayFilters. In the shell works perfect but in my php code never works.
I have tried this way:
$command = new \MongoDB\Driver\Command(
[
'update' => 'students2',
'updates' => [["grades.grade" => ['$gte' => 85]], ['$set' => ["grades.$[elem].mean" => 98 ]], 'arrayFilters' => $filters, 'multi' => true]
]
);
with error: BSON field 'update.updates.grades.grade' is an unknown field
this way:
$db->students2->updateMany([],['$set'=>["grades.$[elem].mean" => 100 ]],['arrayFilters'=> ["elem.grade"=> ['$gte'=>85 ]]]);
with error: "arrayFilters" option has invalid keys for a BSON array
If I execute this command works right but only in one document:
$command = new \MongoDB\Driver\Command(
[
'findAndModify' => 'students2',
'query' => ["grades.grade" => ['$gte' => 85]],
'update' => ['$set' => ["grades.$[elem].mean" => 98 ]],
'upsert' => true,
'returnDocument' => true,
'new' => true,
'arrayFilters' => [['elem.grade'] => ['$gte' => 85]]
]
);
this is my data in mongodb table:
{
"_id" : 1,
"grades" : [
{ "grade" : 80, "mean" : 75, "std" : 6 },
{ "grade" : 85, "mean" : 100, "std" : 4 },
{ "grade" : 85, "mean" : 100, "std" : 6 }
]
}
{
"_id" : 2,
"grades" : [
{ "grade" : 90, "mean" : 100, "std" : 6 },
{ "grade" : 87, "mean" : 100, "std" : 3 },
{ "grade" : 85, "mean" : 100, "std" : 4 }
]
}
What am I doing wrong?
Thanks so much
Try This way
$updateResult = $collection->updateMany(
["inspector" => "J. Clouseau", "Sector" => 4 ],
['$set' => ['Patrolling' => false]]
);
I am working on mongoDB with Laravel using jenssegers. And i am trying to sum based on Abonos.price.
I have a MongoDb document like this:
`{
"_id" : ObjectId("594a89358b85112444002924"),
"cliente" : "blabla",
"tipo" : "bla bla",
"paquete" : "bla bla",
"date" : "2017-06-14",
"content" : "picture",
"cost" : NumberInt(200),
"status" : NumberInt(2),
"Abonos" : [
{
"price" : "200", `enter code here`
"date" : "2017-06-21"
},
{
"price" : "300",
"date" : null
}
], }`
I want to sum Abonos.price to get "500" (200+300)
I have this function in my laravel controller:
$result = Work::raw(function($collection){
return $collection->aggregate(array(
array('$unwind' => '$Abonos'),
array('$group' => array(
"_id" => '$_id',
"total" => array('$sum' => '$Abonos.price')
)),
));});
return $result;
But i get
[{"_id":"594a95cc8b85112444002925","total":0}
instead of
[{"_id":"594a95cc8b85112444002925","total":500}"
I would like to make $return = 500
Now, when I add values to Mongodb using PHP it stores as array:
{ "_id" : ObjectId("591e9b60470e6c500f3c9869"),"value" : [ "mama", "papa" ] }
How to store data for value as object: {"mama" : 1, "papa" : 2}?
I tried:
$data = array("value" => array("mama" => 1, "papa" => 2))
$this->collection->insert($data);
It is inserted as array!
Try using these lines -
$data = (object) ["value" => (object) ["mama" => 1, "papa" => 2]]
$this->collection->insert($data);
It'll create object with mentioned properties.
db.products.insert(
[
{ _id: 11, item: "pencil", qty: 50, type: "no.2" },
{ item: "pen", qty: 20 },
{ item: "eraser", qty: 25 }
]
)
or
{
"_id" : ObjectId("591c382a82956dc8a500002e"),
"name" : "alpesh",
"email" : "admin#gmail.com",
"contact_number" : "0123456789",
"position" : "devloper",
"updated_at" : ISODate("2017-05-17T11:46:50.000Z"),
"created_at" : ISODate("2017-05-17T11:46:50.000Z")
}
I need to join more than two fields in two collections using aggregate $lookup. is it possible to join? please let me know if it is possible. Here i have two collections:
For Example:
"people" collections fields "city,state,country" in "country" collection fields "city_id,state_id,country_id", I want to join this three fields in following collections.
"People"
{
"_id" : 1,
"email" : "admin#gmail.com",
"userId" : "AD",
"userName" : "admin",
"city" : 1,
"state" : 1,
"country" : 1
}
"country"
{
"country_id" : 1,
"userId" : "AD",
"phone" : "0000000000",
"stateinfo":[{
"state_id" : 1,
"state_name" : "State1"
},{
"state_id" : 2,
"state_name" : "State2"
}
],
"cityinfo":[{
"city_id" : 1,
"city_name" : "city1"
},{
"city_id" : 2,
"city_name" : "city2"
}
]
}
This is probably a lot more simple than you think, considering that of course all of the "three" fields are contained within the one "country" document. So it's just a matter of doing the $lookup by "country_id" and then using the retrived content to populate the other fields.
var pipeline = [
{ "$lookup": {
"from": "country",
"localField": "country",
"foreignField": "country_id",
"as": "country"
}},
{ "$project": {
"email": 1,
"userId": 1,
"userName": 1,
"country": {
"$arrayElemAt": [
{ "$filter": {
"input": {
"$map": {
"input": "$country",
"as": "country",
"in": {
"country_id": "$$country.country_id",
"userId": "$$country.userId",
"phone": "$$country.phone",
"stateInfo": {
"$arrayElemAt": [
{ "$filter": {
"input": "$$country.stateInfo",
"as": "state",
"cond": { "$eq": [ "$$state.state_id", "$state" ] }
}},
0
]
},
"cityinfo": {
"$arrayElemAt": [
{ "$filter": {
"input": "$$country.cityinfo",
"as": "city",
"cond": { "$eq": [ "$$city.city_id", "$city" ] }
}},
0
]
}
}
}
},
"as": "country",
"cond": { "$eq": [ "$$country.userId", "$userId" ] }
}},
0
]
}
}}
]
db.people.aggregate(pipeline)
That should give you a result like:
{
"_id" : 1,
"email" : "admin#gmail.com",
"userId" : "AD",
"userName" : "admin",
"country" : {
"country_id" : 1,
"userId" : "AD",
"phone" : "0000000000",
"stateinfo": {
"state_id" : 1,
"state_name" : "State1"
},
"cityinfo": {
"city_id" : 1,
"city_name" : "city1"
}
}
So once the array is matched in by $lookup it all comes down to using $filter to do the matcing and $arrayElemAt to get the first match from each filtered array.
Since the outer array has "inner" arrays, you want to use $map for the "outer" source and apply $filter to each of it's "inner" arrays.
You can get more fancy with $let to get that "reduced" array content down to the returned sub-document and then just directly reference the resulting properties for an even "flatter" response, but the general concept of "matching" the array elements remains the same as above.
For a PHP structure translation:
$pipeline = array(
array(
'$lookup' => array(
'from' => 'country',
'localField' => 'country'
'foreignField' => 'country_id',
'as' => 'country'
)
)
array(
'$project' => array(
'email' => 1,
'userId' => 1,
'userName' => 1,
'country' => array(
'$arrayElemAt' => array(
array(
'$filter' => array(
'input' => array(
'$map' => array(
'input' => '$country',
'as' => 'country',
'in' => {
'country_id' => '$$country.country_id',
'userId' => '$$country.userId',
'phone' => '$$country.phone',
'stateInfo' => array(
'$arrayElemAt' => array(
array(
'$filter' => array(
'input' => '$$country.stateInfo',
'as' => 'state',
'cond' => array( '$eq' => array( '$$state.state_id', '$state' ) )
)
),
0
)
),
'cityinfo' => array(
'$arrayElemAt' => array(
array(
'$filter' => array(
'input' => '$$country.cityinfo',
'as' => 'city',
'cond' => array( '$eq' => array( '$$city.city_id', '$city' ) )
)
),
0
)
)
}
)
),
'as' => 'country',
'cond' => array( '$eq' => array( '$$country.userId', '$userId' ) )
)
),
0
)
)
)
)
);
$people->aggregate($pipeline);
You can usually check your PHP matches a JSON structure when you are working from a JSON example by dumping the pipeline structure:
echo json_encode($pipeline, JSON_PRETTY_PRINT)
And that way you cannot go wrong.
As another final note here, the process after the $lookup is done is quite "complex" even if very efficient. So I would advise that unless there is some need to take this aggregation pipeline further and actually "aggregate" something, then you are probably better off doing that "filtering" in client code rather than doing it on the server.
The client code to do the same thing is far less "obtuse" than what you need to tell the aggregation pipeline to do. So unless this "really" saves you a lot of bandwidth usage by reducing down the matched array, or indeed you if can just "lookup" by doing another query instead, then stick with doing it in code and/or do the seperate query.
MongoDB aggregate query returning empty set .Below is the query i am using in a php script to retrieve data from mongoDB .Please let me know where i am going wrong.
$result = $collection->aggregateCursor([[ '$match'=> [ 'date'=> [ '$gte'=>ISODate("2015-06-01T00:00:00Z"), '$lte'=>ISODate("2015-06-03T00:00:00Z")] ] ],[ '$group'=> [ '_id'=> '$date', 'count'=> [ '$sum'=>1 ] ] ]]);
If i run same query in mongoDB shell.it is showing the output as expected.
db.mnumber.aggregate([{ $match: { date: { $gte:new ISODate("2015-06-01T00:00:00Z"), $lte:new ISODate("2015-06-03T00:00:00Z") } } },{ $group: { _id: "$date", 'count': { $sum:1 } } }])
{ "_id" : ISODate("2015-06-01T00:00:00Z"), "count" : 10000 }
{ "_id" : ISODate("2015-06-02T00:00:00Z"), "count" : 10000 }
{ "_id" : ISODate("2015-06-03T00:00:00Z"), "count" : 10000 }
Sample data in collection:
{
"_id" : ObjectId("55743941789a9abe7f4af3fd"),
"msisdn" : "1234567890",
"act_date" : ISODate("2014-11-24T00:00:00Z"),
"date" : ISODate("2015-06-07T00:00:00Z"),
"recharge_stats" : {
"recharge_amt" : 0,
"rechargetype" : "WEB"
},
"voice_usage" : {
"local_og_mou" : 20,
"local_other_mobile_og_mou" : 0,
"nld_og_mou" : 0,
"nld_other_mobile_og_mou" : 10
},
"gprs_usage" : {
"total_access_count" : 1,
"total_datavolume_mb" : 42
},
"sms_usage" : {
"freesms" : 3,
"local_sms_count" : 0,
"nat_sms_count" : 0,
"inter_sms_count" : 0
},
"campaign_details" : {
"camp_id" : "M01124",
"message" : "Hello .",
"msg_id" : "9174051951412054925609431100",
"cmp_activation_status" : "YES"
}
}
Try to generate a MongoDate() object as follows
$dateFrom = new MongoDate(strtotime("2015-06-01T00:00:00Z"));
$dateTo = new MongoDate(strtotime("2015-06-03T00:00:00Z"));
which you can then use in your aggregation pipeline instead of the MongoDB ISODate objects in your PHP query.
/* Run the command cursor */
$result = $collection->aggregateCursor(
[
[ '$match' => [ 'date'=> [ '$gte' => $dateFrom, '$lte' => $dateTo ] ] ],
[ '$group' => [ '_id' => '$date', 'count' => [ '$sum' => 1 ] ] ]
]
);