I have a candidate Index where documents are structured like so :
{
"_index" : "candidates",
"_type" : "_doc",
"_id" : "a23OcncBXBMGOH6pwXge",
"_version" : 1,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : {
"id" : "413",
"firstname" : "Tania",
"lastname" : "Stroman",
"email" : "Berlin#yahoo.com",
"zip" : "60306",
"city" : "frankfurt",
"birthday" : "1978-11-22",
"tags" : [
"php",
"munich"
],
"location" : {
"lat" : 50.11601257324219,
"lon" : 8.669955253601074
}
}
}
Once a candidate uploads their file, If it's the first uploaded file, I add a field called 'file' to the elastic document. If there are uploaded files in the document already, I push the subsequent uploads to the existing array with the following code :
public function attachCandidateFile($file)
{
$client = ClientBuilder::create()->build();
$params = [
'index' => 'candidates',
'id' => $file['candidate_id']
];
$candidate = $client->get($params);
if (!is_array($candidate['_source']['file'])) {
$candidate['_source']['file'] = [];
}
array_push($candidate['_source']['file'], $file);
$params = [
'index' => 'candidates',
'type' => '_doc',
'id' => $file['candidate_id'],
'body' => [
'doc' => [
'file' => $candidate['_source']['file']
]
]
];
$response = $client->update($params);
echo '<pre>', print_r($response, true) ,'</pre>';
}
Is there a way to update the candidate's files directly with the new object without needing the fetch $candidate['_source']['file'] so as to avoid overriding it ?
Sure -- use an update script when you know which doc to update (using its _id):
POST candidates/_update/a23OcncBXBMGOH6pwXge
{
"script": {
"source": """
if (ctx._source.containsKey('file')) {
ctx._source.file.add(['filename':params.filename]); // adding a hash map -- could be any JSON primitive
} else {
ctx._source.file = [['filename':params.filename]]; // 1-member array
}
""",
"params": {
"filename": "abc"
}
}
}
Alternatively, use the same script as above but under an _update_by_query call. You can target that document (possible even multiple docs) without ever fetching them.
I have a data object below that I tried to test using postman. I just don't know how to make this possible also in laravel's unit testing. I have visited this link but it doesn't helped in my case.
{
"user_id": 1,
"name": "juan",
"address": [
"state": "Auckland",
"country": "New Zealand",
],
"school": [
{
"school_name": "Kristin School",
"year": 2016
},
{
"school_name": "ACG Parnell College",
"year": 2018
},
],
// and more...
}
How can we pass such an object above in unit testing? Is there any way to achieve this?
$response = $this->post('/logbooks/user', ['Authorization': 'Bearer' + $token]);
First to know that such tests are not a "unit test" type.
Note that the code will run and you should be alert to changes that running the code may entail (updating data in the database, contacting external providers).
Of course, all of this can be mocked, and it is recommended that you read about it carefully.
class FooTest extends TestCase {
public function testBar()
{
$response = $this->post('/api/v1/yourapi',
[
"user_id" => 1,
"name" => "juan",
"address" => [
"state" => "Auckland",
"country" => "New Zealand"
],
"school" => [
[
"school_name" => "Kristin School",
"year" => 2016
],
[
"school_name" => "ACG Parnell College",
"year" => 2018
]
]
]);
$response->assertStatus(200);
$response->assertJsonStructure([...]);
$response->assert....();
}
}
As I wrote in the comment below, the JSON you attached was invalid.
You treated the array as an object, adding unnecessary commas.
It is recommended to use an array that the IDE knows to recognize
As you can find in the Laravel docs for HTTP tests, you can send a php array as follows:
$payload = [
"user_id" => 1,
"name" => "juan",
"address" => [
"state" => "Auckland",
"country" => "New Zealand",
],
];
$response = $this->postJson(
'/logbooks/user', $payload, ['Authorization': 'Bearer' + $token]
);
It takes your php $payload array and encodes it as JSON and sends it.
If you have an object you can cast it with $myArray = (array) $myObject.
i have a problem with elasticsearch
when i send request for add nested object with elasticseach script in postman it work but when i wanna send request for add new object in elasticseach , All objects in my index disappear.
it not work , this eliminates all other objects in elasticsearch and only add itself:
$params = [
'script' => [
'source' => 'ctx._source.products.add(params.products)',
'lang'=>'painless',
'params' =>['id'=>1,'name'=>'john']
]
];
$http = new Client();
$result = $http->request('post','http://my_server/new_frotel/_update/123', [
'body' =>$params,
'headers'=>[
'content-type'=>'application/json'
]
])
but it work in postman
POST : http://my_server/new_frotel/_update/123
{
"script": {
"source": "ctx._source.products.add(params.products)",
"lang": "painless",
"params": {
"products": {
"id":1,
"name":"john"
}
}
}
}
I am making a discord webhook for logging something, I have done it with the help of a template (I'm not good at php) and I keep getting the error: {"embeds": ["0"]}
I have already tried researching it, I haven't gotten back anything helpful. Mind the messiness I did this to test.
Here is my code:
<?php
$url = "https://discordapp.com/api/webhooks/xxx"; // Censored for privacy
$hookObject = json_encode([
"username" => "Promotion Logs",
"avatar_url" => "https://cdn.discordapp.com/icons/472520717515096078/60cc7dd2864c95a749516d1213359b67.png",
"tts" => false,
"embeds" => [
[
"title" => "Promotion Logs",
"type" => "rich",
"description" => "",
"url" => "http://police.riverside-roleplay.com/promologs.php",
"color" => hexdec( "0099ff" ),
"fields" => [
[
"name" => "Name",
"value" => "dd",
"inline" => false
],
[
"name" => "Rank",
"value" => "$rank",
"inline" => true
],
[
"name" => "Their name",
"value" => "dd",
"inline" => true
],
[
"name" => "Old rank",
"value" => "dd",
"inline" => true
],
[
"name" => "New rank",
"value" => "dd",
"inline" => true
],
[
"name" => "Reason",
"value" => "dd",
"inline" => true
],
[
"name" => "Date",
"value" => "dd",
"inline" => true
],
]
]
]
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
$ch = curl_init();
curl_setopt_array( $ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $hookObject,
CURLOPT_HTTPHEADER => [
"Length" => strlen( $hookObject ),
"Content-Type" => "application/json"
]
]);
$response = curl_exec( $ch );
curl_close( $ch );
?>
Here is the template I was using:
<?php
// Replace the URL with your own webhook url
$url = "https://discordapp.com/api/webhooks/0000000/ABCDEFGH....";
$hookObject = json_encode([
/*
* The general "message" shown above your embeds
*/
"content" => "A message will go here",
/*
* The username shown in the message
*/
"username" => "MyUsername",
/*
* The image location for the senders image
*/
"avatar_url" => "https://pbs.twimg.com/profile_images/972154872261853184/RnOg6UyU_400x400.jpg",
/*
* Whether or not to read the message in Text-to-speech
*/
"tts" => false,
/*
* File contents to send to upload a file
*/
// "file" => "",
/*
* An array of Embeds
*/
"embeds" => [
/*
* Our first embed
*/
[
// Set the title for your embed
"title" => "Google.com",
// The type of your embed, will ALWAYS be "rich"
"type" => "rich",
// A description for your embed
"description" => "",
// The URL of where your title will be a link to
"url" => "https://www.google.com/",
/* A timestamp to be displayed below the embed, IE for when an an article was posted
* This must be formatted as ISO8601
*/
"timestamp" => "2018-03-10T19:15:45-05:00",
// The integer color to be used on the left side of the embed
"color" => hexdec( "FFFFFF" ),
// Footer object
"footer" => [
"text" => "Google TM",
"icon_url" => "https://pbs.twimg.com/profile_images/972154872261853184/RnOg6UyU_400x400.jpg"
],
// Image object
"image" => [
"url" => "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
],
// Thumbnail object
"thumbnail" => [
"url" => "https://pbs.twimg.com/profile_images/972154872261853184/RnOg6UyU_400x400.jpg"
],
// Author object
"author" => [
"name" => "Alphabet",
"url" => "https://www.abc.xyz"
],
// Field array of objects
"fields" => [
// Field 1
[
"name" => "Data A",
"value" => "Value A",
"inline" => false
],
// Field 2
[
"name" => "Data B",
"value" => "Value B",
"inline" => true
],
// Field 3
[
"name" => "Data C",
"value" => "Value C",
"inline" => true
]
]
]
]
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE );
$ch = curl_init();
curl_setopt_array( $ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $hookObject,
CURLOPT_HTTPHEADER => [
"Length" => strlen( $hookObject ),
"Content-Type" => "application/json"
]
]);
$response = curl_exec( $ch );
curl_close( $ch );
?>
My expected results is to make an embed with the fields I have setup. I had this before then I implemented it to a different page and changed a few things, then it was broken. Actual results is the error {"embeds": ["0"]}
The main problem with your code appear to be that $rank is undefined, as in there's no value in it, so "value" => "$rank", is causing the problem as Discord is expecting a value in it.
Using the code you wrote (and substituting webhook link with functioning link for testing) initially gave a different error:
{"message": "Cannot send an empty message", "code": 50006}
That could be fixed by changing this bit:
CURLOPT_HTTPHEADER => [
"Length" => strlen( $hookObject ),
"Content-Type" => "application/json"
]
into this:
CURLOPT_HTTPHEADER => [
"Length" => strlen( $hookObject ),
"Content-Type: application/json"
]
After that bit had been changed, it now indeed gave out the error {"embeds": ["0"]} as you described. After I define some value for $rank at top, your code works again. So the actual problem is really that the value is undefined.
See full file comparison between your original code and the edited code on my Gist:
https://gist.github.com/mnh48/a707aec600ac74f4e5d50875fcab5d7c
I put 34.2 as example $rank = 34.2;, and the result:
For anyone else coming from search engine
I initially got the same error and I had found the reason, but the reason on my side is different from what OP encountered.
Whenever anyone get this response from Discord webhook:
{"embeds": ["0"]}
It can mean two different thing:
There is invalid field being sent in the body
The limit has been exceeded for certain element
For the first case, it can be:
formatting error:
wrong format in timestamp, it must be in ISO8601 format
wrong format in color, it must be in decimal, anything else are not accepted (yes, even colour name string like "red" are not accepted, convert them to decimal -- red is 16711680, you can use site like SpyColor to check the decimal value)
wrong format in icon_url, avatar_url, or url, all of them must be in http://, https://, (additionally for url that expects image, it can be attachment:// so long the image file is also attached to the request)
invalid value:
using unexpected values, like passing string instead of boolean for inline (there's two strings accepted, probably for compatibility reason: "true" and "false", but any other strings are not accepted, and it's expecting boolean)
empty or null value, if you want it to be empty then don't include it in the first place, or use _ _ as the value
undefined value, check that all variables are actually defined
For the second case, the limit is as follows:
The limit for embed titles are 256 characters
The limit for embed descriptions are 2048 characters
Each field's name is limited to 256 characters
Each field's value is limited to 1024 characters
The limit for footer text is 2048 characters
The limit for author name is 256 characters
There can be 25 fields maximum per message
There can be 10 embeds maximum per message
Total characters overall must not exceed 6000 characters
In my case, it was the latter. I set my email client to send the content of the email as Discord Webhook in embeds > fields > value, and it was passing the whole long email message. The value field has maximum character limit of 1024 but my email content message had 1565 characters.
For anyone else coming across this from google:
Response from API:
{"embeds": ["0"]}
The issue for me was that I was using a float number vars in my JSON.
Wrong json:
{
"allowed_mentions": {
"parse": [
"everyone"
]
},
"embeds": [
{
"author": {
"name": "Name"
},
"title": "Title",
"color": "51281",
"fields": [
{
"name": "Label",
"value": 648.2,
"inline": true
}
]
}
]
}
Right json
{
"allowed_mentions": {
"parse": [
"everyone"
]
},
"embeds": [
{
"author": {
"name": "Name"
},
"title": "Title",
"color": "51281",
"fields": [
{
"name": "Label",
"value": 648,
"inline": true
}
]
}
]
}
I was getting the same error and the problem for me was using env vars in my JSON.
You'll get an error back if url fields aren't valid urls.
e.g "url":"$SOME_VAR"
I believe that this can also happen with other types too!
For anyone coming from Google, I got the same error when the url parameter was invalid.
I had the url as file:///Users/myUser/Downloads/test.html while I was testing and it didn't work. Seems only valid URLs are accepted for webhooks, which makes sense.
Given in the end of the question is an terminal command showing a simple Elasticsearch mapping. I need to set up this kind of mapping for an index using Elasticsearch-PHP. And I need to do this at the time when I am indexing the data.
I know how to index in Elasticsearch-PHP. It will be something like
for($i = 0; $i < 100; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'my_index',
'_type' => 'my_type',
]
];
$params['body'][] = [
'my_field' => 'my_value',
'second_field' => 'some more values'
];
}
$responses = $client->bulk($params);
My question is that how will I set up a Mapping, corresponding to the particular Mapping given below in the elasticsearch-PHP format (I believe it will become an associative array, but I am not sure of further details)?
This is the example ES Mapping, that I want to convert to the format used in PHP:
PUT _template/packets
{
"template": "packets-*",
"mappings": {
"pcap_file": {
"dynamic": "false",
"properties": {
"timestamp": {
"type": "date"
},
"layers": {
"properties": {
"ip": {
"properties": {
"ip_ip_src": {
"type": "ip"
},
"ip_ip_dst": {
"type": "ip"
}
}
}
}
}
}
}
}
}
If you don't update your mapping - you don't have to put mapping each time you re-index data into elasticsearch. But if you do, of you create index with new name you can do this:
$put = [
'mappings' => [
// your mapping here
],
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://yourHost:9200/yourIndex');
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($put));
curl_exec($ch);
or you can use elasticsearch package:
$params = [
'index' => 'yourIndex',
'body' => [
'mappings' => [
// your mapping here
]
]
];
$response = $client->indices()->create($params);