Unrecognized option to $bucket: $group - laravel

getting the above error when i run $bucket with $group in mongodb laravel.
input collection:
{
"id": "n54qllhzwdlxqvy",
"season_id": "vl7oqdehzjxr510",
"status_id": 8,
"venue_id": "",
"referee_id": "",
"neutral": 1,
"note": "",
"home_scores": [0, 0, 0, 0, 0, 0, 0],
"away_scores": [1, 0, 0, 0, 0, 0, 0],
"home_position": "",
"away_position": "",
"coverage": {
"mlive": 0,
"lineup": 0
},
"round": {
"stage_id": "ednm9whz7xoryox",
"round_num": 0,
"group_num": 3
},
"updated_at": "2021-05-03 16:53:52",
"competition_id": "gpxwrxlhdgryk0j",
"competition_name": "Chinese U18 Women's National Games",
"home_team_id": "2y8m4zh8xwjql07",
"home_team_name": "Fujian U18 Women ",
"away_team_id": "8yomo4hvxg2q0j6",
"away_team_name": "Shandong U18 Women",
"match_time": "2021-05-03 15:00:00",
"match_tsp": 1620025200,
"created_at": "2021-05-04 14:33:05"
}
$data = DB::connection('mongodb_football')->collection('match_list')->raw(function ($collection) {
return $collection->aggregate([
[
'$bucket' => [
'groupBy' => '$competition_id',
'boundaries' => ["4zp5rzgh3nq82w1","4zp5rzghjjgq82w", "4zp5rzghkzq82w1","4zp5rzghpvnq82w","4zp5rzghx38q82w","4zp5rzghx5q82w1"],
'default' => "Other",
'output' => [
"data" => [
'$push' => [
"season_id" => '$season_id'
]
]
]
]
]
]);
});
output:
need to group all data based on competition_id and need all the data.

Remove $ prefix from groupBy, boundaries, default, and output.
The $bucket 'groupBy' field must be defined as a $-prefixed path or an expression
It says group by field required reference field that should be prefix by $, but you have assigned it in array bracket [].
Try below syntax, i have not tested yet but it would be,
$data = DB::connection('mongodb_football')->collection('match_list')->raw(function ($collection) {
return $collection->aggregate([
[
'$bucket' => [
'groupBy' => '$competition_id',
'boundaries' => ["4zp5rzgh3nq82w1","4zp5rzghjjgq82w", "4zp5rzghkzq82w1","4zp5rzghpvnq82w","4zp5rzghx38q82w","4zp5rzghx5q82w1"],
'default' => "Other",
'output' => [
"data" => [
'$push' => [
"season_id" => '$season_id'
]
]
]
]
]
]);
});
Playground

Solution
$data = DB::connection('mongodb_football')->collection('match_list')->raw(function ($collection) {
return $collection->aggregate([
[
'$bucket' => [
'groupBy' => '$competition_id',
'boundaries' => ["4zp5rzgh3nq82w1","4zp5rzghjjgq82w", "4zp5rzghkzq82w1","4zp5rzghpvnq82w","4zp5rzghx38q82w","4zp5rzghx5q82w1"],
'default' => "Other",
'output' => [
"data" => [
'$push' => [
"season_id" => '$season_id'
]
]
]
]
]
]);
});

Related

How do I sort a Laravel Collection by an array?

I know this has been asked several times, but none of the answers work for me.
I have a collection of products; each has an eloquent relationship containing multiple items.
Here's how I'm retrieving the collection
$collections = Collection::with('items')->get();
And this is the result of return $collections from the controller.
[
{
"id": 1,
"name": "Product One",
"items": [
{
"id": 1,
"product_id": 1,
"name": "Item One",
},
{
"id": 2,
"product_id": 1,
"name": "Item Two",
},
{
"id": 3,
"product_id": 1,
"name": "Item Three",
},
},
{
"id": 2,
"name": "Product Two",
"items": [
{
"id": 1,
"product_id": 2,
"name": "Item One",
},
{
"id": 2,
"product_id": 2,
"name": "Item Two",
},
{
"id": 3,
"product_id": 2,
"name": "Item Three",
},
}
]
I'd like to sort each product's items in a different order.
I'd like to sort Product One's items as 3, 1, 2 and Product Two's items as 2, 3, 1.
So I created an array of the new sort order, and then added a callback
$newSortOrder = [
1 => [3, 1, 2],
2 => [2, 3, 1]
];
$collections = Collection::with('items')->get();
foreach ($collections as $collection) {
$collection->items->sortBy(function ($model) use ($newSortOrder) {
return array_search($model->id, $newSortOrder[$model->id]);
});
}
dd($collections); <-- this is still in the default sort order from the db
However, when I return $collections, the items are still in the default order. What am I doing wrong?
Edit: tried this as well but with same results; $collection items are returned in the default order.
foreach ($collections as $collection) {
$collection->items->sortBy(function ($model) use ($order) {
return array_search($model->getkey(), $order);
});
}
$sortOrder = [
1 => [3, 1, 2],
2 => [2, 3, 1]
];
$sorted = $products->map(function($product) use ($sortOrder) {
$order = $sortOrder[$product->id];
return [
...$product,
'items' => $product->items->mapWithKeys(
fn($item) => [array_search($item['id'], $order) => $item]
)->sortKeys()
];
});
This Outputs
Illuminate\Support\Collection {#4720
#items: array:2 [
0 => array:3 [
"id" => 1
"name" => "product one"
"items" => Illuminate\Support\Collection {#4722
#items: array:3 [
0 => array:2 [
"id" => 3
"name" => "three"
]
1 => array:2 [
"id" => 1
"name" => "one"
]
2 => array:2 [
"id" => 2
"name" => "two"
]
]
#escapeWhenCastingToString: false
}
]
1 => array:3 [
"id" => 2
"name" => "product two"
"items" => Illuminate\Support\Collection {#4721
#items: array:3 [
0 => array:2 [
"id" => 2
"name" => "two"
]
1 => array:2 [
"id" => 3
"name" => "three"
]
2 => array:2 [
"id" => 1
"name" => "one"
]
]
#escapeWhenCastingToString: false
}
]
]
#escapeWhenCastingToString: false
}
you can recreate items using map().
// not recommend because key does not support for correct item's id
// $newSortOrder = [
// 1 => [3, 1, 2],
// 2 => [2, 3, 1]
// ];
$newSortOrder = [
[
"id" => 1,
"sortOrder" => [3, 1, 2]
],
[
"id" => 2,
"sortOrder" => [2, 3, 1]
],
];
$collections = Collection::with('items')->get();
$sortedCollection = collect($collections)->map(function($item) use($newSortOrder) {
$id = data_get($item,'id');
$name = data_get($item,'name');
$originItems = data_get($item,'items');
$sortOrderList = data_get(collect($newSortOrder)->firstWhere('id',$id),'sortOrder');
$items = collect($sortOrderList)->map(function($sortNumber) use($originItems) {
return collect($originItems)->firstWhere('id',$sortNumber);
});
return compact('id','name','items');
});
dd($sortedCollection); // result

Magento 2 rest api doesn't update salable quantity

I use rest api to create a simple product on my magento. All works correctly except quantity column that is correctly update on "Quantity" column but not on the salable quantity.
Rest call: "www.mysite.com/V1/products"
Array data
$data = [
"product" => [
"sku" => $sku,
"name" => $product_title,
"attribute_set_id" => 4,
"price" => $price,
"status" => 1,
"visibility" => 4,
"type_id" => "simple",
"weight" => "1",
"extension_attributes" => [
"category_links" => [
[
"position" => 0,
"category_id" => "53"
]
],
"stock_item" => [
"qty" => $qty,
"is_in_stock" => true
]
],
"custom_attributes" => [
[
"attribute_code" => "special_price",
"value" => $salable_price
],
[
"attribute_code" => "special_from_date",
"value" => "2021-02-07 00:00:00"
],
[
"attribute_code" => "special_to_date",
"value" => "2091-02-07 00:00:00"
],
[
"attribute_code" => "cost",
"value" => $salable_price
],
[
"attribute_code" => "description",
"value" => $description
],
[
"attribute_code" => "short_description",
"value" => $short_description
]
]
]
];
As you see, qty has been correctly update on qty column but not on the salable quantity. What is my mistake?
Please try this:
"stockItem": {
"is_in_stock": 1,
"qty": 10,
"manage_stock": true,
"use_config_manage_stock": 1
}

How can i use php conditions inside json data?

Below is the code inside my CategoryResource.php
[
'id' => $this->id,
'name' => $this->name,
'categories' => CategoryResource::collection($this->children),
'items' => ItemListResource::collection($this->items)
];
and by this i am getting response like:
{
"status": true,
"data": {
"categories": [
{
"id": 10,
"name": "Fast Food",
"categories": [
{
"id": 11,
"name": "Pizza",
"categories": [],
"items": [
{
"id": 9,
"name": "Ham \u0026 Crab Stick",
"price": "20.00",
"image": "up/products/c11/Mrn4OpjngYRCkRJ28rJ1LbXUOXy0XjTRyXU7eFoi.jpg"
}
]
}
],
"items": []
}
]
}
}
i dont want "categories" : [] when category does not exist for a category.
please suggest some ideas or ways i can deal with this issue.
I assume that CategoryResource::collection($this->children) returns an array, maybe empty or not.
If that's true, then:
$dataArray = [
'id' => $this->id,
'name' => $this->name,
'items' => ItemListResource::collection($this->items)
];
$categories = CategoryResource::collection($this->children);
if (count(categories) > 0) $dataArray['categories'] = $categories;

Laravel reject function on nested collection

I am trying to iterate my collection, which has nested collections, with the collection reject() function and return the original collection with the updated nested data.
So this is my quiz collection
{
"id": 1,
"title": "quiz 1",
"questions": [
{
"id": 1,
"quiz_id": 1,
"question": "q1 - q1",
"answers": [
{
"id": 1,
"question_id": 1,
"answer": "answer to question 1"
},
{
"id": 2,
"question_id": 1,
"answer": "answer to question 1"
}
]
},
{
"id": 2,
"quiz_id": 1,
"question": "q1 - q2",
"answers": [
{
"id": 3,
"question_id": 2,
"answer": "answer to question 1"
}
]
}
]
}
Now I want to iterate through the questions and reject those that were already answered and exist in the result collection. I do so by using the reject() function
$quizResults = [
{
"id": 1,
"user_id": 1,
"quiz_id": 1,
"question_id": 1,
"answer_id": 1,
"correct": 1,
"created_at": null,
"updated_at": null
}
];
$filtered = $quiz->questions->reject(function ($value, $key) use ($quizResult) {
return $quizResult->contains('question_id', $value->id);
});
I want to return the quiz collection with the updated questions (without the rejected questions), but I can't seem to figure out the correct way to accomplish this. (if i return just the $filtered variable i get the correct filtered results, however if i try putting it back in to the $quiz var it won't apply the rejected filter). If I just do
return $quiz
I will get the same original collection with all the questions as if I never ran the reject() function.
How do I make the $quiz->questions = $filtered; ?
Pass it by reference
$filtered = $quiz->questions->reject(function ($value, $key) use (&$quizResult) {
return $quizResult->contains('question_id', $value->id);
});
This is the min steps to reproduce your problem,
$quizResult = [
0 => [
'id' => 1,
'user_id' => 1,
'quiz_id' => 1,
'question_id' => 1,
'answer_id' => 1,
'correct' => 1,
'created_at' => null,
'updated_at' => null,
],
];
$quiz = [
'id' => 1,
'title' => 'quiz 1',
'questions' => [
0 => [
'id' => 1,
'quiz_id' => 1,
'question' => 'q1 - q1',
'answers' => [
0 => [
'id' => 1,
'question_id' => 1,
'answer' => 'answer to question 1',
],
1 => [
'id' => 2,
'question_id' => 1,
'answer' => 'answer to question 1',
],
],
],
1 => [
'id' => 2,
'quiz_id' => 1,
'question' => 'q1 - q2',
'answers' => [
0 => [
'id' => 3,
'question_id' => 2,
'answer' => 'answer to question 1',
],
],
],
],
];
$filtered = collect($quiz['questions'])->reject(function ($value) use ($quizResult) {
return collect($quizResult)->contains('question_id', $value['id']);
});
$quiz['questions'] = $filtered;
return $quiz;
And this the result,
{
"id": 1,
"title": "quiz 1",
"questions": {
"1": {
"id": 2,
"quiz_id": 1,
"question": "q1 - q2",
"answers": [
{
"id": 3,
"question_id": 2,
"answer": "answer to question 1"
}
]
}
}
}
I do not understand why you said it's returning original one.
I had to unset the $quiz['questions'] first so it was like this
unset($quiz['questions']);
$quiz['questions'] = $filtered->flatten();
return $quiz;
and the result was as intended:
{
"id": 1,
"title": "quiz 1",
"questions": [
{
"id": 2,
"quiz_id": 1,
"question": "q1 - q2",
"answers": [
{
"id": 3,
"question_id": 2,
"answer": "answer to question 1"
}
]
}
]
}

How can i update the ids field with this rethinkdb document structure?

Having trouble trying to update the ids field in the document structure:
[
[0] {
"rank" => nil,
"profile_id" => 3,
"daily_providers" => [
[0] {
"relationships" => [
[0] {
"relationship_type" => "friend",
"count" => 0
},
[1] {
"relationship_type" => "acquaintance",
"ids" => [],
"count" => 0
}
],
"countries" => [
[0] {
"country_name" => "United States",
"count" => 0
},
[1] {
"country_name" => "Great Britain",
"count" => 0
}
],
"provider_name" => "foo",
"date" => 20130912
},
[1] {
"provider_name" => "bar"
}
]
}
]
In JavaScript, you can do
r.db('test').table('test').get(3).update(function(doc) {
return {daily_providers: doc("daily_providers").changeAt(
0,
doc("daily_providers").nth(0).merge({
relationships: doc("daily_providers").nth(0)("relationships").changeAt(
1,
doc("daily_providers").nth(0)("relationships").nth(1).merge({
ids: [1]
})
)
})
)}
})
Which becomes in Ruby
r.db('test').table('test').get(3).update{ |doc|
{"daily_providers" => doc["daily_providers"].changeAt(
0,
doc["daily_providers"][0].merge({
"relationships" => doc["daily_providers"][0]["relationships"].changeAt(
1,
doc["daily_providers"][0]["relationships"][1].merge({
ids => [1]
})
)
})
)}
}
You should probably have another table for the daily providers and do joins.
That would make things way more simpler.

Resources