I have this PHP snippet:
<?php
$json = '{"number":[{"value":"5121387","operator":"="},{"value":"5121391","operator":"="}]}';
$array = json_decode($json, true);
echo http_build_query($array);
and it generates this (for better readability I decoded those %XY Brackets):
number[0][value]=5121387&number[0][operator]=%3D&number[1][value]=5121391&number[1][operator]=%3D
This is excellent and works for my case.
When I try to generate this form-URL-encoding by Open-API/Swagger-UI it doesnt work this way:
[
'name' => 'number',
'in' => 'query',
'style' => 'form',
'description' => 'some description',
'explode'=> true,
'collectionFormat' => 'multi',
'schema' => [
[...],
],
];
instead it generates me this GET-query appended to my URL:
number[value]=5121387&number[operator]=%3D&number[value]=5121391&number[operator]=%3D
the Open-API Doc says the same - but it doesnt say how to fix this - the problem is the missing Array-indicators e.g. "[0]":
I have already checked the swagger-ui-bundle.js from the Swagger-ui to alter the form-encoding myself - but it is minified and I dont get it...
Do you have any Idea how I can teach my .yaml or Swagger-UI to add those numbered brackets for Arrays?
Related
I'm trying to use the Firebase PHP API to update/append a document field's array with a map
I have the following code in Python that works fine
ref = db.collection(u'jobs').document(jobId)
ref.update({
u'messages': firestore.ArrayUnion([{
u'category': u'0',
u'message': u'TEST',
u'sender': u'TEAM',
}])
})
Though when I try to replicate it in PHP, it doesn't work. I tried a lot of different ways to view the errors, but all I get is 500 INTERNAL SERVER ERROR.
require 'vendor/autoload.php';
use Google\Cloud\Firestore\FirestoreClient;
use Google\Cloud\Firestore\FieldValue;
$firestore = new FirestoreClient([
'projectId' => 'XXX-XX',
'credentials' => 'key.json'
]);
$jobId = "XXXX";
$docRef = $firestore->collection('jobs')->document($jobId);
$docRef->update([
'messages' => FieldValue::arrayUnion([{
'category' : '0',
'message' : 'TEST',
'sender' : 'TEAM',
}])
]);
I looked up samples of Array Union in PHP, adding data with PHP. I've tried a lots of variations of : or => or arrayUnion([]) or arrayUnion({[]}) to no avail.
Any idea what is causing this?
Looks like there's a few things going wrong here.
First, PHP uses arrays for both maps and "normal" arrays. There is no object literal ({}) in PHP. Array values are specified using the => operator, not :.
Second, DocumentReference::update() accepts a list of values you wish to change, with the path and value. So an update call would look like this:
$docRef->update([
['path' => 'foo', 'value' => 'bar']
]);
You can use DocumentReference::set() for the behavior you desire. set() will create a document if it does not exist, where update() will raise an error if the document does not exist. set() will also replace all the existing fields in the document unless you specify merge behavior:
$docRef->set([
'foo' => 'bar'
], ['merge' => true]);
Therefore, your code can be re-written as either of the following:
$jobId = "XXXX";
$docRef = $firestore->collection('jobs')->document($jobId);
$docRef->set([
'messages' => FieldValue::arrayUnion([[
'category' => '0',
'message' => 'TEST',
'sender' => 'TEAM',
]])
], ['merge' => true]);
$jobId = "XXXX";
$docRef = $firestore->collection('jobs')->document($jobId);
$docRef->update([
[
'path' => 'messages', 'value' => FieldValue::arrayUnion([[
'category' => '0',
'message' => 'TEST',
'sender' => 'TEAM',
]])
]
]);
One final thing to note: arrayUnion will not append duplicate values. So if the value you provide (including all keys and values in the nested map) already exists, it will not be appended to the document.
If you haven't already, turn up error reporting in your development environment to receive information about why your code is failing. PHP will inform you about the parse errors your snippet included, and the Firestore client will give you errors which can often be quite useful.
From Firebase Documentation:
$cityRef = $db->collection('cities')->document('DC');
// Atomically add a new region to the "regions" array field.
$cityRef->update([
['path' => 'regions', 'value' => FieldValue::arrayUnion(['greater_virginia'])]
]);
I would assume you would like something like this:
$docRef = $firestore->collection('jobs')->document($jobId);
// Atomically add new values to the "messages" array field.
$docRef->update([
['path' => 'messages', 'value' => FieldValue::arrayUnion([[
'category' : '0',
'message' : 'TEST',
'sender' : 'TEAM',
]])]
]);
I am new to the Laravel. I have not tried this in browser I am using tests for this.
I have test that looks like this:
public function testStoreRequestValid()
{
$data = [
'name' => 'New Item',
'parameter.count' => '3',
'parameter.0.parameter_id' => '4',
'parameter.0.value_id' => '',
'parameter.0.value' => 'text',
'parameter.1.parameter_id' => '1',
'parameter.1.value_id' => '2',
'parameter.1.value' => 'Yes',
'parameter.2.parameter_id' => '2',
'parameter.2.value_id' => '',
'parameter.2.value' => '10'
];
$response = $this->call('post', '/item', $data);
// ...
}
When I try to fetch data using:
$parameterCount = $request->input('parameter.count');
I get null value (if I use has method it gets false).
When I have tried to use square brackets I have got the results, but I want the API to be usable with JSON too without too much hastle in the JS.
How do I solve this in the most clean way?
Dot in Laravel has a special meaning so you can't really use arrays which have dots in their keys. You should declare your data as follows:
<?php
$data = [];
array_set($data,'name','New Item');
array_set($data,'parameter.count','3');
array_set($data,'parameter.0.parameter_id','4');
array_set($data,'parameter.0.value_id','');
array_set($data,'parameter.0.value','text');
array_set($data,'parameter.1.parameter_id','1');
array_set($data,'parameter.1.value_id','2');
array_set($data,'parameter.1.value','Yes');
array_set($data,'parameter.2.parameter_id','2');
array_set($data,'parameter.2.value_id','');
array_set($data,'parameter.2.value','10');
I am using Aptana Studio 3 and it's highlighting the square brackets as a potential error. It inteferes with my coding because I keep thinking that am messing somewhere. The code is running well and no error is displayed on the console. How do I fix it?
$series_data[] = array(
'name' => 'Brands',
'colorByPoint' => true,
'data'=> array(
['name' => 'Nairobi, KE', 'y' => 56.33],
['name'=> 'Kisumu, KE', 'y'=>64.03 ],
['name'=> 'New Yorm, USA', 'y'=>44.03 ]
The error is displayed between ( and [ as below:
data=array([
The [...] array syntax is only valid in PHP 5.4 and higher, so possibly the problem is that your IDE is configured to expect PHP 5.3 syntax? Check the IDE's config.
Also, can I recommend that you be a bit more consistent in which array syntax you use? There's nothing inherently wrong with mixing between array(...) and [...] notations, but it does make the code harder to read.
Check this
you forgot to use )
$series_data[] = array(
'name' => 'Brands',
'colorByPoint' => true,
'data'=> array(
['name' => 'Nairobi, KE', 'y' => 56.33],
['name'=> 'Kisumu, KE', 'y'=>64.03 ],
['name'=> 'New Yorm, USA', 'y'=>44.03 ]
)
);
In my example code I am using the php client library, but it should be understood by anyone familiar with elasticsearch.
I'm using elasticsearch to create an index where each document contains an array of nGram indexed authors. Initially, the document will have a single author, but as time progresses, more authors will be appended to the array. Ideally, a search could be executed by an author's name, and if any of the authors in the array get matched, the document will be found.
I have been trying to use the documentation here for appending to the array and here for using the array type - but I have not had success getting this working.
First, I want to create an index for documents, with a title, array of authors, and an array of comments.
$client = new Client();
$params = [
'index' => 'document',
'body' => [
'settings' => [
// Simple settings for now, single shard
'number_of_shards' => 1,
'number_of_replicas' => 0,
'analysis' => [
'filter' => [
'shingle' => [
'type' => 'shingle'
]
],
'analyzer' => [
'my_ngram_analyzer' => [
'tokenizer' => 'my_ngram_tokenizer',
'filter' => 'lowercase',
]
],
// Allow searching for partial names with nGram
'tokenizer' => [
'my_ngram_tokenizer' => [
'type' => 'nGram',
'min_gram' => 1,
'max_gram' => 15,
'token_chars' => ['letter', 'digit']
]
]
]
],
'mappings' => [
'_default_' => [
'properties' => [
'document_id' => [
'type' => 'string',
'index' => 'not_analyzed',
],
// The name, email, or other info related to the person
'title' => [
'type' => 'string',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
'authors' => [
'type' => 'list',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
'comments' => [
'type' => 'list',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
]
],
]
]
];
// Create index `person` with ngram indexing
$client->indices()->create($params);
Off the get go, I can't even create the index due to this error:
{"error":"MapperParsingException[mapping [_default_]]; nested: MapperParsingException[No handler for type [list] declared on field [authors]]; ","status":400}
HAD this gone successfully though, I would plan to create an index, starting with empty arrays for authors and title, something like this:
$client = new Client();
$params = array();
$params['body'] = array('document_id' => 'id_here', 'title' => 'my_title', 'authors' => [], 'comments' => []);
$params['index'] = 'document';
$params['type'] = 'example_type';
$params['id'] = 'id_here';
$ret = $client->index($params);
return $ret;
This seems like it should work if I had the desired index to add this structure of information to, but what concerns me would be appending something to the array using update. For example,
$client = new Client();
$params = array();
//$params['body'] = array('person_id' => $person_id, 'emails' => [$email]);
$params['index'] = 'document';
$params['type'] = 'example_type';
$params['id'] = 'id_here';
$params['script'] = 'NO IDEA WHAT THIS SCRIPT SHOULD BE TO APPEND TO THE ARRAY';
$ret = $client->update($params);
return $ret;
}
I am not sure how I would go about actually appending a thing to the array and making sure it's indexed.
Finally, another thing that confuses me is how I could search based on any author in the array. Ideally I could do something like this:
But I'm not 100% whether it will work. Maybe there is something fundemental about elasticsearch that I am not understanding. I am completely new to so any resources that will get me to a point where these little details don't hang me up would be appreciated.
Also, any direct advice on how to use elasticsearch to solve these problems would be appreciated.
Sorry for the big wall of text, to recap, I am looking for advice on how to
Create an index that supports nGram analysis on all elements of an array
Updating that index to append to the array
Searching for the now-updated index.
Thanks for any help
EDIT: thanks to #astax, I am now able to create the index and append to the value as a string. HOWEVER, there are two problems with this:
the array is stored as a string value, so a script like
$params['script'] = 'ctx._source.authors += [\'hello\']';
actually appends a STRING with [] rather than an array containing a value.
the value inputted does not appear to be ngram analyzed, so a search like this:
$client = new Client();
$searchParams['index'] = 'document';
$searchParams['type'] = 'example_type';
$searchParams['body']['query']['match']['_all'] = 'hello';
$queryResponse = $client->search($searchParams);
print_r($queryResponse); // SUCCESS
will find the new value but a search like this:
$client = new Client();
$searchParams['index'] = 'document';
$searchParams['type'] = 'example_type';
$searchParams['body']['query']['match']['_all'] = 'hel';
$queryResponse = $client->search($searchParams);
print_r($queryResponse); // NO RESULTS
does not
There is no type "list" in elasticsearch. But you can use "string" field type and store array of values.
....
'comments' => [
'type' => 'string',
'analyzer' => 'my_ngram_analyzer',
'term_vector' => 'yes',
'copy_to' => 'combined'
],
....
And index a document this way:
....
$params['body'] = array(
'document_id' => 'id_here',
'title' => 'my_title',
'authors' => [],
'comments' => ['comment1', 'comment2']);
....
As for the script for apending an element to array, this answer may help you - Elasticsearch upserting and appending to array
However, do you really need to update the document? It might be easier to just reindex it as this is exactly what Elasticsearch does internally. It reads the "_source" property, does the required modification and reindexes it. BTW, this means that "_source" must be enabled and all properties of the document should be included into it.
You also may consider storing comments and authors (as I understand these are authors of comments, not the document authors) as child document in ES and using "has_child" filter.
I can't really give you specific solution, but strongly recommend installing Marvel plugin for ElasticSearch and use its "sense" tool to check how your overall process works step by step.
So check if your tokenizer is properly configured by running tests as described at http://www.elastic.co/guide/en/elasticsearch/reference/1.4/indices-analyze.html.
Then check if your update script is doing what you expect by retrieving the document by running GET /document/example_type/some_existing_id
The authors and comments should be arrays, but not strings.
Finally perform the search:
GET /document/_search
{
'query' : {
'match': { '_all': 'hel' }
}
}
If you're building the query yourself rather than getting it from the user, you may use query_string with placeholders:
GET /document/_search
{
'query' : {
'query_string': {
'fields': '_all',
'query': 'hel*'
}
}
}
Looked around but didn't see this anywhere, the basic question is, can I use a filter_input_array were the value of one of my keys is an enum (think mysql enum), protocode would be something like this.
print_r(filter_input_array(INPUT_POST, [
'CanBeFooOrBar' => [
'filter' => FILTER_VALIDATE_ENUM,
'options' => ['foo', 'bar'],
]
]));
If this is possible, what is my filter, and if not, what would be the best way to replicate this behavior?
There isn't a specific list/enum filter.
The closest you get is FILTER_VALIDATE_REGEXP with something like:
print_r(filter_input_array(INPUT_POST, [
'CanBeFooOrBar' => [
'filter' => FILTER_VALIDATE_REGEXP,
'options' => ["regexp" => "/^(foo|bar)$/"],
]
]));
Personally I'm using something more fancy, which simplifies it to:
print $_POST->in_array("CanBeFooOrBar", "foo,bar");