How can create a test in laravel for check load relationships - laravel

public function test_show_role_should_return_actions()
{
$this->actingAs($this->user, 'api');
$this->withHeaders(['Accept' => 'application/json',])
->get(route('roles.show', ['role' => $this->role->id]))
->assertJsonStructure([
"data" => [
"name",
"actions" => [
"name",
"code"
]
]
]);
}
when I run the test,I have this error:
Tests\Feature\Role\RoleTest::test_show_role_should_return_actions
Failed asserting that an array has the key 'name'.
Even when I remove the "name",I get an error for the "actions" key.

public function test_show_role_should_return_actions()
{
$this->actingAs($this->user, 'api');
$this->getJson(route('roles.show', ['role' => $this->role->id]))
->assertJsonStructure([
'data' => [
'*' => [
'name',
'actions' => [
'*' => [
'name',
'code'
]
]
]
]
]);
}

Related

Search dynamic array index MongoDB

I'm relatively new to MongoDB and trying to figure out how to search for data which has dynamic keys, my dataset is below:
[
'id' => '60bb040f7e589378f644f9a2',
'name' => 'foo',
'settings' => [
'foo' => [
'type' => 'custom',
'enabled' => 'yes'
],
'bar' => [
'type' => 'custom',
'enabled' => 'no'
],
'baz' => [
'type' => 'custom',
'enabled' => 'no'
]
]
]
I want to get the search inside settings, and get all the settings which has enabled as yes.
I've tried this
return Customer::raw(function($collection) {
return $collection->aggregate([
[
'$search' => [
"wildcard" => [
'query' => 'yes',
'path' => 'settings.*.enabled'
]
]
]
]);
});
I am getting the following errror:
Unrecognized pipeline stage name: '$search'
I've also tired using $match, like this
Customer::raw(function($collection)
{
return $collection->aggregate([
[
'$match' => [
"settings.*.enabled" => 'yes'
]
],
]);
})
But it does't return any value.
Any direction on achieving this will be helpful. Thanks!
Ok this is a bit complex but is all I can come up with myself:
Customer::raw(function($collection)
{
return $collection->aggregate([
[
'$addFields' => [
"settingsArray" => [
'$objectToArray' => '$settings'
]
]
],
[
'$unwind' => [
'path' => '$settingsArray'
]
],
[
'$match' => [
'settingsArray.v.enabled' => 'yes'
]
],
[ '$unset' => 'settingsArray' ],
[
'$group' => [
'_id' => '$_id',
doc => [ '$first' => '$$ROOT' ]
]
],
[
'$replaceRoot' => [
'newRoot' => '$doc'
]
]
]);
});
This should return all documents with at least one enabled setting.
A key point about aggregation is that the pipeline works on all documents that the previous stage of the pipeline returned.
Here's the aggregation pipeline explanation:
$addFields will convert the settings object to an array of format [ { k: key, v: value } ] e.g. [ { k: 'foo', 'v': { type: 'custom', enabled: 'yes' } }, ... ]
$unwind will "unwind" the document and "replace" it with X copies of the same document one for each entry in the newly added settingsArray array. The settingsArray at this stage is not an array anymore but a single entry of type { k: key, v: value }. In short you'd get one document per setting
$match will do the actual matching for any document with an enabled setting (remember now each document will only have a single setting as settingsArray
$unset will remove the settingsArray from each document bringing it back to its original format
$group will group all documents by their _id and use the first result of each group as a doc entry. Each document will now be like { _id: <id>, doc: <original document> }
$replaceRoot will set the root of the document to doc and therefore bring the documents back to their original format.
Would love to hear if anyone else has a better solution here.

Laravel: How to access Object inside an array

I trying to return access the attributes inside a array of object and it is giving this error Exception: Property [id] does not exist on this collection instance.
Here is what I have tried:
protected function formatted($classroom)
{
return [
'courses' => [
'id' => $classroom->courses->id,
'name' => $classroom->courses->name,
'slug' => $classroom->courses->slug,
'coursteachers' => [
'id' => '$classroom->courses->coursteachers->id',
'email' => '$classroom->courses->coursteachers->email',
'uid' => '$classroom->courses->coursteachers->uid',
]
],
];
}
And here is the actual data:
"courses": [
{
"id": 1,
"name": "Analytics",
"slug": "analytics",
"status_id": 1,
"deleted_at": null,
"pivot": {
"classroom_id": 2,
"courses_id": 1
},
"coursteachers": [
{
"id": 3,
"uid": "S0120-46890",
"email": "teacher#vschool.com",
"user_type": "Teacher",
}]
}]
You need to iterate through courses and also courseteachers since they both represent an array but rather an object
protected function formatted($classroom)
{
$result = [];
foreach($classroom->courses as $course) {
$result[] = [
'courses' => [
'id' => $classroom->courses->id,
'name' => $classroom->courses->name,
'slug' => $classroom->courses->slug,
'coursteachers' => $this->getCourseTeachers($cours)
],
];
}
return $result;
}
private function getClassroomTeachers($classroom) {
$result = [];
foreach($classroom->courses as $cours)
{
foreach ($cours->coursteachers as $key => $teacher) {
$result[] = [
// 'coursteachers'=> [
'id' => $teacher->id,
'email' => $teacher->email,
'uid' => $teacher->uid,
'last_name' => $teacher->profile->last_name,
'first_name' => $teacher->profile->first_name,
'middle_name' => $teacher->profile->middle_name,
// ],
];
}
}
return $result;
}
Since courses is an array, you should pick an object using the proper index.
Foe example: try $classroom->courses[0]->id instead of $classroom->courses->id. Here, '0' is the index.
Also it is better if you check if the index exists before you do it. For an example.
'id' : isset($classroom->courses[$index]) ? $classroom->courses[$index]->id : ''
Edit:
In case of a Eloquent collection you should use $classroom->courses->get($index)->id instead of array like retrieval.

ElasticSearch 7 - combine filters

I use ES 7 and Laravel implementation, I want to combine a range and a term match, according to documentation, I did this :
$items = $client->search([
'index' => $instance->getSearchIndex(),
'type' => $instance->getSearchType(),
'body' => [
'size' => 50,
'query' => [
'bool' => [
'must' => [
'multi_match' => [
'fields' => config('elasticsearch.fields'),
'query' => $query,
],
],
'filter' => [
'bool' => [
'must' => [
'range' => [
'note' => [
'gte' => config('elasticsearch.note_minimum')
]
],
'term' => [
'type_video_id' => 5
],
],
],
],
]
],
],
]);
And got this error :
"parsing_exception","reason":"[range] malformed query, expected
[END_OBJECT] but found [FIELD_NAME]
I only found documentation and examples for ES 2 about combining queries, did something change ?
I want my query to match the fields, and be filtered according to filter.
Here is the right way to do this:
$items = $client->search([
'index' => $instance->getSearchIndex(),
'type' => $instance->getSearchType(),
'body' => [
'size' => 50,
'query' => [
'bool' => [
'must' => [
'multi_match' => [
'fields' => config('elasticsearch.fields'),
'query' => $query,
]
],
'filter' => [
[
'range' => [
'note' => [
'gte' => config('elasticsearch.note_minimum')
]
]
],
[
'term' => [
'type_video_id' => 5
]
]
]
]
]
]
]);
I don't have a way to test this, but I'm seeing a couple brackets where you need curlies. Also, don't you need you need $ before those "config"?
{
"query" => {
"bool" => {
"must" => [
{
"multi_match" => {
"query" => $query,
"fields" => $config('elasticsearch.fields')
}
}
],
"filter" => {
{
"range" => {
"note" => {
"gte" => $config('elasticsearch.note_minimum')
}
}
},
{
"term" => {
"type_video_id" => {
"value" => "5"
}
}
}
}
}
}
}
If this doesn't work, can you paste what the string looks like after your variables get rendered?

Unknown key for a VALUE_STRING in [index]

I'm trying to find a way where I can build my $params array using the native syntax to search for a post which name is equal to 'test':
$params = [
"index" => "post_index",
"type" => "post",
'body' => [
'query' => [
'match' => [
'name' => 'test'
]
]
]
];
$result = $finder->find($params);
Unfortunately I'm getting this error:
Unknown key for a VALUE_STRING in [index].
I know that I can use some Elastic\Query\Match to build my query.
Just I fixed my $params array this way :
$q = [
'query' => [
'match' => [
'title' => 'test'
]
]
];

Elastic Search: ES-PHP Client how to create GEOPOINT Index

I am trying to create an index that should contain GEOPoint by using the Elastic Search PHP client -> https://www.elastic.co/guide/en/elasticsearch/client/php-api/5.0/index.html
My Code is as follow
$params = [
'index' => 'sweden_codes',
'type' => 'sweden_c',
'body' => [
'mappings' => [
'location' => [
'properties' => [
'pin' => [
'properties' => [
'location' => [
'type' => 'geo_point'
]
]
]
]
],
'text' => $code->City,
'pin' => [
'location' => [
'lat' => $code->Latitude,
'lon' => $code->Longitude
]
]
]
]
];
$client = ClientBuilder::create()
->setSSLVerification(false)
->setHosts(["elasticsearch:9200"])->build();
The Problem is when i go into kibana it say " No Compatible Fields: The "sweden_codes" index pattern does not contain any of the following field types: geo_point"
can anyone please have a look into the issue and let me know whats wrong with my mapping and index creation
Here is the Code for Mappings that works for me
$params = [
'index' => 'sweden_postal_codes',
'body' => [
'mappings' => [
'codes' => [
'properties' => [
'location' => [
'type' => 'geo_point'
],
'city' => [
'type' => 'string'
]
]
]
]
]
];
$client = ClientBuilder::create()
->setSSLVerification(false)
->setHosts(["elasticsearch:9200"])->build();
// Adding the index into the ES Cluster
$response = $client->indices()->create($params);
Here is the code for document indexing that worked for me
$params = [
'index' => 'sweden_postal_codes',
'type' => 'codes',
'id' => 2,
'body' => [
'location' => [
'lat' => 30.5268956,
'lon' => 79.2289643
],
'city' => 'Stockholm'
]
];
$client = ClientBuilder::create()
->setSSLVerification(false)
->setHosts(["elasticsearch:9200"])->build();
// Adding the index into the ES Cluster
$response = $client->index($params);

Resources