So my code here:
$featurecollection = ("FeatureCollection");
$test[] = array (
"type" => $featurecollection,
$features[] = array($images)
);
file_put_contents($cache,json_encode($test));
results in the following json:
[
{
"type":"feature",
"0":[
[
{
"title":"some title",
"src":"value",
"lat":"value",
"lon":"value"
},
{
"title":"some title",
...
But I need to nest things differently and I'm perplexed on how the php array should be constructed in order to get a result like:
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"geometry":{
"coordinates":[
-94.34885,
39.35757
],
"type":"Point"
},
"properties":{
"latitude":39.35757,
"title":"Kearney",
"id":919,
"description":"I REALLY need new #converse, lol. I've had these for three years. So #destroyed ! :( Oh well. Can't wait to get a new pair and put my #rainbow laces through. #gay #gaypride #bi #proud #pride #colors #shoes #allstar #supporting ",
"longitude":-94.34885,
"user":"trena1echo5",
"image":"http://images.instagram.com/media/2011/09/09/ddeb9bb508c94f2b8ff848a2d2cd3ece_7.jpg",
"instagram_id":211443415
}
},
What would the php array look like for that? I'm thrown off by the way everything is nested but still has a key value.
Here's how I'd represent that in PHP:
array(
'type' => 'FeatureCollection',
'features' => array(
array(
'type' => 'Feature',
'geometry' => array(
'coordinates' => array(-94.34885, 39.35757),
'type' => 'Point'
), // geometry
'properties' => array(
// latitude, longitude, id etc.
) // properties
), // end of first feature
array( ... ), // etc.
) // features
)
So to get that structure, each feature has to be an associative array of:
type,
geometry - an associative array of:
coordinates - an indexed array of values,
type
properties - an associative array of values like latitude, longitude, id etc.
It's times like these when I prefer languages that distinguish between lists (array(1, 2, 3)) and dictionaries or maps (array('a' => 1, 'b' => 2)).
With PHP 5.4 and above:
$array = [
'type' => 'FeatureCollection',
'features' => [
[
'type' => 'Feature',
'geometry' => [
'coordinates' => [-94.34885, 39.35757],
'type' => 'Point'
], // geometry
'properties' => [
// latitude, longitude, id etc.
] // properties
], // end of first feature
[] // another feature, and so on
] // end of features
];
For the PHP script below:
<?php
header('Content-type=> application/json');
echo json_encode($array);
This is the JSON output;
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"coordinates": [
-94.34885,
39.35757
],
"type": "Point"
},
"properties": []
},
[]
]
}
Related
I am rather new to PHP so I don't know how to work with these datasets. I make a MySQL select and get back an object like this:
{
"membername": "NAME",
"bookingdate": "2020-02-03",
"categoryid": 1,
"dailyworkhourssum": "7.70"
},
{
"membername": "NAME",
"bookingdate": "2020-02-03",
"categoryid": 3,
"dailyworkhourssum": "1.2"
},
{
"membername": "NAME",
"bookingdate": "2020-02-05",
"categoryid": 3,
"dailyworkhourssum": "7.70"
},
I want to iterate through this and in the end it should look like this:
{
"membername": "NAME",
"bookingdate": "2020-02-03",
"categoryid1": true,
"categorid3": true,
"dailyworkhourssum1": "7.70",
"dailyworkhourssum3": "1.2"
},
{
"membername": "NAME",
"bookingdate": "2020-02-05",
"categoryid": 3,
"dailyworkhourssum": "7.70"
},
What this does is that it merges tow fields together (if they have the same bookingdate )into one so that I can display it in a table without reoccurring dates.
My problem:
I don't know what this type of data is called.
I don't know how to create something like this.
I can add fields to this type of data with $data->newField = example so I think that this is an object.
In JS it's called an object, but in PHP you will use an associative array instead.
In your case, I think, you have an array of associative arrays. It looks like this:
$books = [
[
"membername" => "NAME",
"bookingdate" => "2020-02-03",
"categoryid" => 1,
"dailyworkhourssum" => "7.70"
],
[
"membername" => "NAME",
"bookingdate" => "2020-02-03",
"categoryid" => 3,
"dailyworkhourssum" => "1.2"
],
[
"membername" => "NAME",
"bookingdate" => "2020-02-05",
"categoryid" => 3,
"dailyworkhourssum" => "7.70"
]
];
If you wanna merge an arrays with the same "bookingdate" then I recommend you to loop through this array and add its elements to another associative array with bookingdates as keys, and check, in case if there is such key already, then merge the arrays, like this:
$merged = [];
foreach ($books as $book) {
$date = $book['bookingdate'];
if (isset($merged[$date])) {
$merged[$date] = $merged[$date] + $book;
} else {
$merged[$date] = $book;
}
}
I think that it is not a valid code (no time, sorry), but I hope, you cautch the idea.
If you want a 'list' instead of an associative array, than you can do this:
$mergedList = array_values($merged);
Thus you will rid of string keys.
If I understood correctly, you obtain a table with 4 columns an a variable number of rows and you want to transform it to a table with a variable number of columns. For that, using a data structure where every item is different from the previous one can make everything harder than it needs. I'd suggest you use a fixed structure:
// I'm assuming you have a PHP array as starting point
$input = [
[
'membername' => 'NAME',
'bookingdate' => '2020-02-03',
'categoryid' => 1,
'dailyworkhourssum' => '7.70',
],
[
'membername' => 'NAME',
'bookingdate' => '2020-02-03',
'categoryid' => 3,
'dailyworkhourssum' => '1.2',
],
[
'membername' => 'NAME',
'bookingdate' => '2020-02-05',
'categoryid' => 3,
'dailyworkhourssum' => '7.70',
],
];
$output = [];
foreach ($input as $data) {
// We'll group by booking date
if (!isset($output[$data['bookingdate']])) {
$output[$data['bookingdate']] = [
'membername' => $data['membername'],
'bookingdate' => $data['bookingdate'],
'categoryid' => $data['categoryid'],
'dailyworkhourssum' => [],
];
}
// A single date may have several daily work hours
$output[$data['bookingdate']]['dailyworkhourssum'][] = $data['dailyworkhourssum'];
}
// We discard array keys (we only needed them to group)
echo json_encode(array_values($output));
[{
"membername": "NAME",
"bookingdate": "2020-02-03",
"categoryid": 1,
"dailyworkhourssum": ["7.70", "1.2"]
}, {
"membername": "NAME",
"bookingdate": "2020-02-05",
"categoryid": 3,
"dailyworkhourssum": ["7.70"]
}]
Wherever you consume this JSON you just need to loop the dailyworkhourssum array. You may also want to loop the entire structure before printing the table and keep a counter in order to determine the maximum number of columns so you can draw empty cells where needed (tables are rectangular).
I am using the PHP MongoDB\Driver\Manager and I want to query by creating a MongoDB\Driver\Query.
So I have the following collection design:
{
"_comment": "Board",
"_id": "3",
"player": "42",
"moves": [{
"_id": "1",
"piece": "b3rw4",
"from_pos": "E2",
"to_pos": "E4"
}]
}
How can i query this collection to receive, for all boards of a specific player all moves with min(id)? This means I first want to filter all boards, to get only boards with player ID. Then I want to search all those board's "moves" fields, where I want the min(_id) of that "moves" field.
I currently have this query:
$filter = ['player' => '93'];
$options = [
'projection' => ['_id' => 0,
'moves' => 1]
];
$query = new MongoDB\Driver\Query($filter, $options);
This results in finding all "moves" arrays by Player 93.
How can I then filter all those "moves" fields by only getting the moves with min(_id)?
Ok, so I figured it out. I simply had to use an aggregation pipeline.
Here is the shell command which gives the expected output:
db.boards.aggregate( [
{
$match: {'player': '93'}
},
{
$unwind: {path: '$moves'}
},
{
$group:
{
_id: '$_id',
first_move: { $min: '$moves._id' },
from_pos : { $first: '$moves.from_pos' },
to_pos: { $first: '$moves.to_pos' }
}
}
])
Here is the corresponding PHP MongoDB code using Command and aggregate:
$command = new MongoDB\Driver\Command([
'aggregate' => 'boards',
'pipeline' => [
['$match' => ['player' => '93']],
['$unwind' => '$moves'],
['$group' => ['_id' => '$_id',
'firstMove' => ['$min' => '$moves._id'],
'from_pos' => ['$first' => '$moves.from_pos'],
'to_pos' => ['$first' => '$moves.to_pos']
]
]
],
'cursor' => new stdClass,
]);
$manager = new MongoDB\Driver\Manager($url);
$cursor = $manager->executeCommand('db', $command);
I have a query like
'aggs' => [
'deadline' => [
'date_histogram' => [
'field' => 'deadline',
'interval' => 'month',
'keyed' => true,
'format' => 'MMM'
]
]
]
the result I am getting are buckets with keys as month names.
The problem I am facing is the buckets with the month names as keys for a previous year are over written by another month of the next year (because obviously the key is same).
I want results where doc-count of buckets of previous which are over written merge with the doc_count of the next.
You can either add a separate month field during indexing and perform aggregation on it or use below script
{
"size": 0,
"aggs": {
"deadline": {
"histogram": {
"script": { "inline" : "return doc['deadline'].value.getMonthOfYear()" },
"interval": 1
}
}
}
}
Creating a separate month field will have better performance
Replace the format from MMM to YYYY-MMM as below:
'aggs' => [
'deadline' => [
'date_histogram' => [
'field' => 'deadline',
'interval' => 'month',
'keyed' => true,
'format' => 'YYYY-MMM'
]
]
]
After this you can handle the merging process at your application level
I have this array:
$arr = array(
'reportDescription' => array(
'reportSuiteID' => 'globretailprod',
'elements' => array(
0 => array(
'id' => $queryElement
)
),
'metrics' => array(
0 => array(
'id' => $queryMetric
)
)
)
);
I'm trying to insert some code into the array using an if command. This is what I have:
if (isset($querySegment)) {
$arr['reportDescription']['segments'] = $querySegment;
}
However that gives me the wrong result, what I am trying to achieve is this:
{
"reportDescription": {
"reportSuiteID": "rbsglobretailprod",
"dateFrom": "2018-09-09",
"dateTo": "2018-09-10",
"dateGranularity": "day",
"metrics": [{
"id": "pageviews"
}],
"elements": [{
"id": "page"
}],
"segments": [{
"id": "jjj"
}]
}
}
Notice there are two issues with this. Firstly, segments isn't isn't insert with an id, it's just inserted as a value. Secondly, I am a bit concerned about the trailing comma after metrics in my original array, since I need to be able to add a comma after the metrics array if I do include segments.
Just use the same format as you use for the other items to get the same structure...
if (isset($querySegment)) {
$arr['reportDescription']['segments'] = array(
0 => array(
'id' => $querySegment
)
);
}
As for the comma, this should be added automatically as needed if your using json_encode()
I have the following type of occurrence in my Mongo documents.
"tags" : [ [ "narnia" ], [ "aslan" ], [ "winter" ], [ "heaven" ] ]
I need to know how to find this document by matching all of any number of the tags. I.e. Narnia AND Aslan (but not Narnia OR Aslan).
The query needs to be made with in PHP.
So far I only have it working for a single tag. I.e.
$filter['tags'] = array('$in' => array(array('Narnia')));
As Hussain mentioned in comments - you might want to revise that document structure as seems like you're storing unnecessary arrays.
Otherwise, what you're trying to do could be done with an $and statement (example without the nested arrays):
PRIMARY> db.wardrobe.find({ $and: [ { tags: "narnia" }, { tags: "tugboat" } ] })
//returns nothing
PRIMARY> db.wardrobe.find({ $and: [ { tags: "narnia" }, { tags: "winter" } ] })
//returns { "_id" : ObjectId("521067a48202463b88c2a0c9"), "tags" : [ "narnia", "aslan", "winter", "heaven" ] }
In PHP:
//With your nested arrays:
$filter = array(
'$and' => array(
array('tags' => array('narnia') ),
array('tags' => array('aslan') )
)
);
//With a simple array:
$filter = array(
'$and' => array(
array('tags' => 'narnia'),
array('tags' => 'aslan')
)
);
$mongoClient->selectCollection('cwlewis', 'wardrobe')->find( $filter );