Insert multi elements in mongodb with laravel 9 - php

I have below json package like below :
{
transaction_state: "PAID",
transaction_code: "CGKFT20200715121",
transaction_order: 104182381,
koli_data: [
{
koli_width: 50,
koli_height: 100,
koli_custom_field: {
awb: null,
price: null
}
},
{
koli_width: 20,
koli_height: 50,
koli_custom_field: {
awb: null,
price: null
}
}
],
currentLocation: {
name: "London",
code: "LNDN01",
type: "Agent"
}
}
I can do insert to my mongodb (embedded document) but i am confusing with koli_data part. It's multi elements and how to insert it with laravel 9.
For the rest, i can do it with below code :
Transaction::create([
'transaction_state' => $request->input('transaction_state'),
'currentLocation.name' => $request->input('currentLocation.name'),
I have tried with below code :
$koli_datas = $request->input('koli_data');
$koli_insert = array();
for($i= 0; $i < count($request->input('koli_data')); $i++){
$koli_insert[] = [
'koli_data.koli_width' => $koli_datas[$i]['koli_width'],
'koli_data.koli_height' => $koli_datas[$i]['koli_height']
];
}
and put $koli_insert into Transaction create but not working. Any advice? Thanks

Related

MongoDB find with key that starts with a string pattern

I'm trying to fetch a mongodb data using PHP.
My Data is in the following format:
$document = $collection->findOne(
array('_id' => 'set1'),
array('projection' => array('_id' => 1,'data'=>1))
);
Result:
{
"_id": "set1",
"data": {
"IND": {
"2015-01": 0.6753404,
"2015-02": 1.0502269,
"2015-03": 1.0902269
},
"AUS": {
"2015-01": 0.6753404,
"2015-02": 1.0502269,
"2015-03": 1.0902269
},
"IND_123": {
"2015-01": 0.6753404,
"2015-02": 1.0502269,
"2015-03": 1.0902269
}
}
}
I am trying to fetch the output such that the result only has "IND" and "IND_123".
Is there a way to write the projection such that the result only provides "IND*"
The following provides only "IND"
$document = $collection->findOne(
array('_id' => 'set1'),
array('projection' => array('_id' => 1,'data.IND'=>1))
);
You can achieve it using an aggregation pipeline, like this:
db.collection.aggregate([
{
"$match": {
"_id": "set1"
}
},
{
"$project": {
data: {
"$arrayToObject": {
"$filter": {
"input": {
"$objectToArray": "$data"
},
"as": "item",
"cond": {
"$regexMatch": {
"input": "$$item.k",
"regex": "IND.*"
}
}
}
}
}
}
}
])
Playground link.
Here, we match the required document using $match. Then we, recompute the data field in $project, we first convert the data object to an array using $objectToArray, and filter all keys matching the pattern IND.* using $filter. Finally, we convert the filtered array back to an object using $arrayToObject.

How to manipulate data objects and arrays using Laravel Map function?

Code:
$loans = Loan::select('date_release')
->where('invalid',false)
->where('transaction_year', $transyear)
->get()
->groupBy(function($date) {
return Carbon::parse($date->date_release)->format('m'); // grouping by months
});
$loanmcount = [];
$loanArr = [];
foreach ($loans as $key => $value) {
$loanmcount[(int)$key] = count($value);
}
for($i = 1; $i <= 12; $i++){
if(!empty($loanmcount[$i])){
$loanArr[$i] = $loanmcount[$i];
}else{
$loanArr[$i] = 0;
}
}
$loanTypeCount = Loan::select(['loan_type AS name', DB::raw('count(loan_type) AS y')])
->groupBy('loan_type')
->orderBy(DB::raw('y'), 'desc')
->where('transaction_year', $transyear)
->where('invalid', false)
->get();
$loanTypeCount->map(function($loan)use($loanArr) {
$loan->data = $loanArr;
return $loan;
})
Output:
var_dump(json_encode($loanTypeCount));
string(433) "[{"name":"Salary","y":"6","data":{"1":0,"2":0,"3":0,"4":0,"5":2,"6":1,"7":3,"8":1,"9":1,"10":0,"11":0,"12":0}},{"name":"Emergency","y":"1","data":{"1":0,"2":0,"3":0,"4":0,"5":2,"6":1,"7":3,"8":1,"9":1,"10":0,"11":0,"12":0}}]"
Months were represented by numbers instead of month name. Also, the format is not in array form just like the desired output shown below.
Desired Output:
[
{
name: "Salary",
y: "1",
data: [
[
"January",
0.1
],
[
"February",
1.3
],
]
},
{
name: "Emergency",
y: "2",
data: [
[
"March",
0.1
],
[
"April",
1.3
],
]
}
]
What is the solution for this one? Can't figure this out. Please help. THank you.
in PHP the function has a private scope ,so you can't access the variable normally inside a function.you have to manually pass it to the function
try:
$loanTypeCount->map(function ($loan) use ($loanArr) {
$loan->data = $loanArr;
return $loan;
});

Decoding a multidimensional Json array and seperate it into 3 different arrays

I am receiving the json payload below from a webservice and I am trying to separate it into 3 different arrays using loops after decoding whlist keeping the same array keys:
{
"id": 5705376,
"title": "Satellite Installation",
"created_at": "2017-09-07T14:02:19.000Z",
"updated_at": "2017-09-07T14:02:19.000Z",
"customer_id": 3126803,
"way_points": [{
"id": 7405587,
"lat": -26.0578251,
"lng": 28.02189520000002,
"task_id": 5705376,
"done": false,
"allow_editing_inventory": true,
"customer_contact_ids": [3126803],
"customer": {
"original_phone_number": null,
"last_open_at": null,
"last_order_at": null,
"uploaded_profile_image": {
"url": "/images/avatar.png"
},
"original_lat": null,
"original_lng": null,
"district": null,
"house_number": null,
"street": null
},
"full_address": "8 Anslow Ln, Bryanston, Sandton, 2191, South Africa"
}],
"customer": {
"id": 3126803,
"name": "Lance",
"address": "8 Anslow Ln, Bryanston, Sandton, 2191, South Africa",
"lat": -26.0578251,
"lng": 28.0218952,
"created_at": "2017-08-29T10:00:32.360Z",
"updated_at": "2017-09-07T14:02:19.860Z",
"phone": null,
"merchant_id": 11221,
"allow_login": false,
"stripe_id": null,
"original_phone_number": null,
"last_open_at": null,
"last_order_at": null,
"uploaded_profile_image": {
"url": "/images/avatar.png"
},
"original_lat": null,
"original_lng": null,
"house_number": null,
"street": null
},
"late": false,
"external_id": "5705376",
"uuid": "28095e33-b30c-4e35-98d2-aae6ad428f66",
"dispatcher_id": null,
"team_ids": [12422],
"ready_to_execute": true,
"tip_driver_enabled": false,
"automatically_assigned": false,
"task_inventories": null,
"task_notes": null
}
For the values in the "way_points" key i want to come up with one array called waypoint after decoding whilst ignoring the customers array in it. I also want to change the "id" key name to "waypoint_id" in the process.
For the values in the "customers" key (in the main array) I want to come up with one array called "waypoint" after decoding whilst assigning the value of the "url"
key to the "uploaded profile image" key. I also want to change the "id" key name to "customer_id" in the process.
Any element that is outside of the arrays mentioned above (thus elements in the main array that are not assigned to arrays), I want them to form an array called "orders".
How can i go about doing this. I am new at LOOPS
First you'll need to decode the json encoded string into a usable format, either array or an object. You can find all possible options for json_decode here.
$inputArray = json_decode($inputString, true);
Now for the loop. To keep it simple, you can initialize the three arrays you need firsthand as empty arrays. Then, in the loop, simply check for the key value and choose what array to append the data to.
$waypoints = array();
$customers = array();
$orders = array();
$count = 0;
foreach($inputArray as $key => $element) {
/* using if statements */
if($key === 'way_points') {
$waypoints[] = $element;
}
elseif($key === 'customer') {
$customers[] = $element;
}
else {
$orders[$count][$key] = $element;
}
/* using a switch/case */
switch($key) {
case 'way_points':
$waypoints[] = $element;
break;
case 'customer':
$customers[] = $element;
break;
default:
$orders[$count][$key] = $element;
break;
}
$count++;
}
At this point you should have all the data you need, but we still haven't changed the keys. You could leave it as-is, after all it is pretty self-explanatory that the id key in $waypoints reprensents the waypoint_id. However, if you do absolutely need to change the key, there's a few ways to do this. You can loop over the newly formed $waypoints array and modify the keys in this new loop.
$waypoints = change_keys($waypoints);
function change_keys($arr) {
return array_map(function($waypoint) {
return array(
'waypoint_id' => $waypoint['id'],
'lat' => $element['lat'],
/* remaining fields */
);
}, $arr);
}
Or you can cut the amount of steps and do it in the initial foreach loop
$waypoints = array();
$customers = array();
$orders = array();
$count = 0;
foreach($inputArray as $key => $element) {
if($key === 'way_points') {
$waypoints[] = array_map(function($element) {
return array(
'waypoint_id' => $element['id'],
'lat' => $element['lat'],
/* remaining fields */
);
}, $arr);
}
/* ... */
}
You can find more info on array_map here.
As an aside, as #jeroen mentionned in the comments, you can simply use json_decode and you'll be left with a usable associative array. to loop over the waypoints for example, you would simply write foreach($myArray[waypoints] as $key => $waypoint).

PHP syntax for Mongo $set order statement

I am attempting to update multiple array elements using a PHP version of the query described in how to update sequence number in mongodb safely
Which describes the query:
db.so.update(
{ _id: new ObjectId("4f55e7ba362e2f2a734c92f8")},
{ $set : { 'subs.1.order' : 3, 'subs.2.order' : 2 } }
);
I'm building a query to add an 'order' field to my document
{
"_id": {
"$oid": "5209acfd0de2316335000001"
},
"bookListId": "116ad5af-7cc6-4652-9bb3-aea852e584e8",
"favoriteBook": [
{
"title": "One Favorite Book",
},
{
"title": "Another Favorite Book",
},
{
"title": "A Third Favorite Book",
}
]
}
..and am doing it in PHP with
$criteria = array('bookListId' => $bookListId);
$favoriteBookOrder = array();
for($i=0;$i<sizeof($order);$i++) {
$key = 'favoriteBook.'.($i+1).'.order';
$val = $order[$i];
$favoriteBookOrder[] = array($key=>intval($val));
}
$setFavoriteBookOrder = array('$set' => $favoriteBookOrder);
$collection->update($criteria, $setFavoriteBookOrder);
but this doesn't produce any result because the query doesn't have the correct organization of arrays..
error_log(json_encode($setupdated));
outputs
{"$set":[{"favoriteBook.1.order":2},{"favoriteBook.2.order":1},{"favoriteBook.3.order":3}]}
which if you notice has too many quotes, brackets around the entire array, and curly braces around each item. I believe this is what is causing the error:
"Invalid modifier specified: $set"
What is the correct syntax for building the array in PHP? Thanks!
EDIT
this is the fix
$favoriteBookOrder[] = array($key=>intval($val));
should be
$favoriteBookOrder[$key] = intval($val);
also i removed the +1 from $i because Mongo indexes are 0 based
correct query now
{"$set":{"favoriteBook.0.order":1,"favoriteBook.1.order":2,"favoriteBook.2.order":3}}
To make you query work right you have to change one line:
$favoriteBookOrder[] = array($key=>intval($val));
to
$favoriteBookOrder[$key] = intval($val);
But I think you wont be happy with result, because it will something like this:
"favoriteBook" : {
"0" : { "order" : NumberLong(123) },
"1" : { "order" : NumberLong(321) },
"2" : { "order" : NumberLong(456) }
}
I suggest you rewrite code in this way:
for($i=0;$i<sizeof($order);$i++)
$favoriteBookOrder[$i]['order'] = $order[$i];
$setupdated = array('$set' => ['favoriteBookOrder' => $favoriteBookOrder]);
and you'll get:
"favoriteBookOrder" : [
{ "order" : NumberLong(123) },
{ "order" : NumberLong(321) },
{ "order" : NumberLong(456) }
]
P.S. you can play with $pushAll modificator instead of $set, it could be more suitable for you.

Mongodb find if field exists using a wherein

Essentially is it possible to find documents based on there sub document using $in. For example say I had:
array(
'item.1',
'item.2',
'item.3
)
would return document that have:
{
item {
1: {
}
}
}
{
item {
2: {
}
}
}
{
item {
3: {
}
}
}
I know if I had one I could use db.inventory.find( { qty: { $exists: true, $nin: [ 5, 15 ] } } ) but how would I do that with a $in?
You can use a query of this form:
db.collection.find ( { $or : [
{"item.1":{$exists:true}},
{"item.2":{$exists:true}},
{"item.3":{$exists:true}}
] } );
This will return any document which has one or more of "item.X" in this case 1, 2 or 3 set.

Categories