unmarshalItem DynamoDB & PHP not working - php

I wanted to unmarshal the dynamodb scan query response and here is my code
$client = $this->getClient();
$result = $client->scan([
'ExpressionAttributeValues' => [
':v1' => [
'S' => "200",
],
],
'FilterExpression' => 'id = :v1',
'ProjectionExpression' => "entryStamp",
'TableName' => $this->table,
]);
return $this->unmarshalItem($result['Items']);
It returns error "Unexpected type: entryStamp."

I was searching for this myself and it doesn't seem possible at the moment.
I didn't find anything specifically about PHP but this thread describe the exact same problem with GO.
So the best way to go about it is to do what Saurabh advised in his comment:
$result = $this->client->query($params);
$data = [];
foreach( $result['Items'] as $item)
{
$data[] = $marshaler->unmarshalItem($item);
}
return $data;

Related

PHP AWS Athena: Need to execute queries against athena

I need to run queries against AWS Athena from one of my PHP applications. I have used the documentation from AWS as well as another forum to try and compile the code I need to achieve this. Can you please go through the code and validate/comment/correct where necessary? Most of the code makes sense to me except for the waitForSucceeded() function? I have never seen a function defined this way?
require "/var/www/app/vendor/autoload.php";
use Aws\Athena\AthenaClient;
$options = [
'version' => 'latest',
'region' => 'eu-north-1',
'credentials' => [
'key' => '12345',
'secret' => '12345'
];
$athenaClient = new Aws\Athena\AthenaClient($options);
$databaseName = 'database';
$catalog = 'AwsDataCTLG';
$sql = 'select * from database limit 3';
$outputS3Location = 's3://BUCKET_NAME/';
$startQueryResponse = $athenaClient->startQueryExecution([
'QueryExecutionContext' => [
'Catalog' => $catalog,
'Database' => $databaseName
],
'QueryString' => $sql,
'ResultConfiguration' => [
'OutputLocation' => $outputS3Location
]
]);
$queryExecutionId = $startQueryResponse->get('QueryExecutionId');
var_dump($queryExecutionId);
$waitForSucceeded = function () use ($athenaClient, $queryExecutionId, &$waitForSucceeded) {
$getQueryExecutionResponse = $athenaClient->getQueryExecution([
'QueryExecutionId' => $queryExecutionId
]);
$status = $getQueryExecutionResponse->get('QueryExecution')['Status']['State'];
print("[waitForSucceeded] State=$status\n");
return $status === 'SUCCEEDED' || $waitForSucceeded();
};
$waitForSucceeded();
$getQueryResultsResponse = $athenaClient->getQueryResults([
'QueryExecutionId' => $queryExecutionId
]);
var_dump($getQueryResultsResponse->get('ResultSet'));
From what is can see, it should work properly. What log do you have on execution?
waitForSucceeded() is a closure, aka anopnymous function.
You can find some documentation/ detail here:
https://www.php.net/manual/fr/functions.anonymous.php
https://www.php.net/manual/fr/class.closure.php
So here is what the closure do:
// Declare your closure and inject scope that will be use inside
$waitForSucceeded = function () use ($athenaClient, $queryExecutionId, &$waitForSucceeded) {
$getQueryExecutionResponse = $athenaClient->getQueryExecution([
'QueryExecutionId' => $queryExecutionId
]);
$status = $getQueryExecutionResponse->get('QueryExecution')['Status']['State'];
print("[waitForSucceeded] State=$status\n");
// If status = SUCCEEDED, return some result, else relaunch the function
return $status === 'SUCCEEDED' || $waitForSucceeded();
};
// Launch the function, which must return true when $status === 'SUCCEEDED'
$waitForSucceeded();
$getQueryResultsResponse = $athenaClient->getQueryResults([
'QueryExecutionId' => $queryExecutionId
]);
var_dump($getQueryResultsResponse->get('ResultSet'));

Receive data in Json in PHP

I am posting data to my script file to receive data. In my script file, File.php, I am not able to get the object patient in the dumped results. When i do var_dump($get_patient_info->patient);,
it throws an error saying Object {patient} not found.
Could i be mapping the data wrongly?
PS: Beginner in Laravel
SendingData Controller
$hospitalData = [];
$hospitalData[] = [
'patient' => 'Mohammed Shammar',
'number' => '34',
],
$url = "https://example.com/file.php";
$client = new Client();
$request = $client->post($url, [
'multipart' => [
[
'name' => 'patient_info',
'contents' => json_encode($hospitalData),
],
],
]);
$response = $request->getBody();
return $response;
File.php
$get_patient_info = $_POST['patient_info'];
var_dump($get_patient_info);
Results
string(189) "[{"patient":"Mohammed Shammar","number":"34"}]"
You can json_decode and fetch the data as follows,
$temp = json_decode($get_patient_info);
echo $get_patient_info[0]->patient;
json_decode — Decodes a JSON string
Hope this helps.

php full text search in elasticsearch

I have a json file which I looped through it and index it in elastic. and after that I want to be able to search through my data.
this is my json file :
https://github.com/mhndev/iran-geography/blob/master/tehran_intersection.json
which looks like :
{
"RECORDS":[
{
"first":{
"name":"ابن بابویه",
"slug":"Ibn Babawayh"
},
"second":{
"name":"میرعابدینی",
"slug":"Myrabdyny"
},
"latitude":"35.601605",
"longitude":"51.444208",
"type":"intersection",
"id":1,
"search":"ابن بابویه میرعابدینی,Ibn Babawayh Myrabdyny,ابن بابویه تقاطع میرعابدینی,Ibn Babawayh taghato Myrabdyny",
"name":"ابن بابویه میرعابدینی",
"slug":"Ibn Babawayh Myrabdyny"
},
...
]
}
when my query is : "mir", I expect my result to be records which has "mirabedini", "mirdamad", "samir", and every other word which contains this string.
but I just get words which are exactly "mir"
and this is my php code for search :
$fields = ['search','slug'];
$params = [
'index' => 'digipeyk',
'type' => 'location',
'body' => [
'query' => [
'match' => [
'fields' => $fields,
'query' => $_GET['query']
]
],
'from' => 0,
'size' => 10
]
];
$client = ClientBuilder::create()->build();
$response = $client->search($params);
and also this my php code for indexing documents.
$client = ClientBuilder::create()->build();
$deleteParams = ['index' => 'digipeyk'];
$response = $client->indices()->delete($deleteParams);
$intersections = json_decode(file_get_contents('data/tehran_intersection.json'), true)['RECORDS'];
$i = 1;
foreach($intersections as $intersection){
echo $i."\n";
$params['index'] = 'digipeyk';
$params['id'] = $intersection['id'];
$params['type'] = 'location';
$params['body'] = $intersection;
$response = $client->index($params);
$i++;
}
I'm using php 7 and elasticsearch 2.3
match query doesn't support wildcard query by default, so you have to use wildcard instead of that.
$fields = ['search','slug'];
$params = [
'index' => 'digipeyk',
'type' => 'location',
'body' => [
'query' => [
'wildcard' => [
'query' => '*'.$_GET['query'].'*'
]
],
'from' => 0,
'size' => 10
]
];
$client = ClientBuilder::create()->build();
$response = $client->search($params);
For more information about wildcard in elastic visit following link : https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html
For that:
'query' => $_GET['query']
You will be burn in hell :D

ElasticSearch PHP SDK search returning null on match_all query

I recently tried to use ES. So I set it up in a cloud 9 environnement. I inserted data using a curl request file and I can see them with
http://mydomain/ingredients/aliments/_search?size=350&pretty=true
I then tried to set up elastic SDK (v.2.0) with Silex but I can't get the same output...
Here is my code :
$client = $app['elasticsearch'];
$params = array(
'size' => 350,
'index' => 'ingredients',
'type'=>'aliment',
'body' => array(
'query'=>array(
'match_all' => new \stdClass()
)
)
);
$ingredients = $client->search($params);
The output is NULL but when I do the following :
$params = array(
'index' => 'ingredients',
'type' => 'aliment'
);
$count = $client->count($params);
The output is as expected : {"count":240,"_shards":{"total":5,"successful":5,"failed":0}}
I've already spent a few hours trying to figure what's going on, I tried to replace the 'query' args with a json string, I tried empty array instead of the new stdClass but nothing seems to work.
Edit : I read the documentation again and tried the official example :
$client = $app['elasticsearch'];
$params = [
"search_type" => "scan", // use search_type=scan
"scroll" => "30s", // how long between scroll requests. should be small!
"size" => 50, // how many results *per shard* you want back
"index" => "ingredients",
"body" => [
"query" => [
"match_all" => []
]
]
];
$output = $client->search($params);
$scroll_id = $output['_scroll_id']; /*<<<This works****/
while (\true) {
// Execute a Scroll request
$response = $client->scroll([
"scroll_id" => $scroll_id, //...using our previously obtained _scroll_id
"scroll" => "30s" // and the same timeout window
]
);
var_dump($response); /*<<<THIS IS NULL****/
...
}
And unfortunately got same null result...
What am I doing wrong ?
Thanks for reading.
In my case it works this way:
$json = '{
"query": {
"match_all": {}
}
}';
$params = [
'type' => 'my_type',
'body'=> $json
];
I found out that the inserted data was malformed.
Accessing some malformed data via browser URL seems to be OK but not with a curl command line or the SDK.
Instead of {name:"Yaourt",type:"",description:""} , I wrote {"name":"Yaourt","description":""} in my requests file and now everything work as expected !
#ivanesi 's answer works. You may also try this one:
$params["index"] = $indexName;
$params["body"]["query"]["match_all"] = new \stdClass();

sending array via query string in guzzle

Guzzle client creates by default from this code
$client->get('https://example.com/{?a}', array('a' => array('c','d')));
this url
https://example.com/?a=c,d
What is the best practice to send array in query string in RESTful application? The question is, how can I determine on the server side whether c,d is a string or an array? Isn't it better to send arrays using square brackets, e.g. a[]=c&a[]=d? How can I set Guzzle to use square brackets? Or it is better to use JSON encoded variables? On the server side I'm using Tonic.
Working Solution:
$vars = array('state[]' => array('Assigned','New'), 'per_page' => $perPage, 'page' => $pageNumber);
$query = http_build_query($vars, null, '&');
$string = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '=', $query); // state[]=Assigned&state[]=New
$client = new Client([follow instruction to initialize your client ....]);
$response = $client->request('GET', $uri, ['query' => $string]);
Now you have same name parameters in your request.
Dung.
Source: http_build_query with same name parameters
It seems the answer is here.
I wanted to do something like ?status[]=first&status[]=second
You can do this in Guzzle like shown in the link above:
$client = new Client('http://test.com/api');
$request = $client->get('/resource');
$query = $request->getQuery();
$query->set('status', array('first', 'second'));
Guzzle has a helper function you can use called build_query(). This uses PHP's http_build_query().
Here's an example of how to use it:
$params = [
'a[]' => [
'c',
'd'
],
'page' => 1
];
$query = \GuzzleHttp\Psr7\build_query($params);
$response = $client->request('GET', 'https://example.com/', [
'query' => $query
]);
I'm not 100% sure this quite answers the question. But I found the question while looking for how to construct complex queries using Guzzle and none of the answers here were the solution I ended up using. I'm adding it here in case it's ever useful for any other devs.
Using Guzzle 6, you can do this type of request:
$endPoint = "https://example.com";
$queryParams = [
'a' => [
[
"b" => "c"
]
]
];
$options = [
'debug' => true, // so you can see what the request looks like
'query' => $queryParams
];
$client->request('GET', $endPoint, $options);
As a real world example, query params like this:
$queryParams = [
'filters' => [
[
"field" => "status",
"value" => "open",
"operator" => "equal"
],
[
"field" => "total",
"operator" => "greater_than",
"value" => 50
],
],
'limit' => 500,
'start' => 7
];
produce a url like this:
https://example.com?filters=[{"field":"status","operator":"equal","value":"open"},{"field":"total","operator":"less_than","value":50}]&limit=500&start=7
The point being that the query key of the $options array, seems very powerful. I'd recommend having a play with that before going down the route of writing complex regular expressions.
$query = array('x' => array(
'a',
'b',
'c'
));
$query_string = http_build_query($query, null, '&'); //build query string
$query_string = preg_replace('/%5B(?:[0-9]|[1-9][0-9]+)%5D=/', '[]=', $query_string); //x[]=a&x[]=b
$response = $guzzle->client->get($path, array('query' => $query_string)); //Make guzzle request
return json_decode($response->getBody()->getContents()); //Return JSON decoded array
This is how you can process x with array of values in guzzle, tested with version 6 or later

Categories