PHP MongoDB SUM all columns - php

Is there anyway in which MongoDB aggregate framework can be used to sum up all the columns or an array of columns rather than just one?
Each row has a 'category id'. I'm hoping to filter by a specific category id and then output a row which is the sum of each of the columns. As I wont be needing all of the columns, it would be better if I could specify columns to increase performance.
I have seen examples of this done with 1 column however not with multiple columns.
Below is example data
{ "type" : "A", "a" : 1, "b" : 2, "c" : 3, "d" : 4 }
{ "type" : "A", "a" : 10, "b" : 20, "c" : 30, "d" : 40 }
{ "type" : "B", "a" : 1, "b" : 2, "c" : 3, "d" : 4 }
{ "type" : "B", "a" : 10, "b" : 20, "c" : 30, "d" : 40 }
The result therefore when the type is B would be
{ "type" : "B", "a" : 11, "b" : 22, "c" : 33, "d" : 44 }
As can be seen, each of the columns have been summed up, and a single row is returned with the sum of each column.
I am using PHP and the latest version of MongoDB with Debian
Thanks

We don't have your data for a clear example, but you seem to be basically looking for the $add operator which "add" a list of supplied values together. So given a sample of documents:
{ "type" : "A", "a" : 1, "b" : 2, "c" : 3, "d" : 4 }
{ "type" : "A", "a" : 10, "b" : 20, "c" : 30, "d" : 40 }
{ "type" : "B", "a" : 1, "b" : 2, "c" : 3, "d" : 4 }
{ "type" : "B", "a" : 10, "b" : 20, "c" : 30, "d" : 40 }
There is this example to "add" all the "columns" together for "a", "b" and "c" only. Also grouping by "type":
db.collection.aggregate([
{ "$group": {
"_id": "$type",
"total": { "$sum": { "$add": [ "$a", "$b", "$c" ] } }
}}
])
You can also use $add with $project if you do not need to $group or are otherwise working with data at a different level.
The result on this data would be:
{ "_id" : "B", "total" : 66 }
{ "_id" : "A", "total" : 66 }
What you are actually asking though is just doing a $sum for each column:
db.collection.aggregate([
{ "$group": {
"_id": "$type",
"a": { "$sum": "$a" },
"b": { "$sum": "$b" },
"c": { "$sum": "$c" },
"d": { "$sum": "$d" }
}}
])
Which produces:
{ "_id" : "B", "a" : 11, "b" : 22, "c" : 33, "d" : 44 }
{ "_id" : "A", "a" : 11, "b" : 22, "c" : 33, "d" : 44 }

Related

How to move element to another array based from id_item

I have a array, but for now, the array is still based on id_order, , like this :
here my controller
public function detail()
{
$data = Order::with('detail')->get();
return $data;
}
result:
[
{
"id": 1, //id_order
"order_number" : "IT.123.76",
"status" : "Pending",
"details" : [
{
"id" : 1,
"id_order" : 1,
"id_item" : 2, //based from this
"name" : "Avocado Juice",
"qty" : 7
},
{
"id" : 2,
"id_order" : 1,
"id_item" : 3, //based from this
"name" : "Orange Juice",
"qty" : 2
},
{
"id" : 3,
"id_order" : 1,
"id_item" : 5, //based from this
"name" : "Mango Juice",
"qty" : 1
}
]
},
{
"id": 2, //id_order
"order_number" : "IT.123.78",
"status" : "Pending",
"details" : [
{
"id" : 4,
"id_order" : 2,
"id_item" : 2, //based from this
"name" : "Avocado Juice",
"qty" : 1
},
{
"id" : 5,
"id_order" : 2,
"id_item" : 9, //based from this
"name" : "Ice Tea",
"qty" : 2
}
]
}
}
]
How to change the structure of the array to be like this(based id_item and name item becomes the key in each element) and also for qty per item calculated, for example = avocado juice has 2 orders, first order has qty: 7 and second order qty: 1 then sums 8 results?
[
{
"qty_total" : 8, // from 7+1 in avocado juice
"Avocado Juice" : [
{
"id" : 1, //From id_order
"id_item" : 2, //Avocado Juice
"order_number" : "IT.123.76",
"qty" : 7
},
{
"id" : 2, //From id_order
"id_item" : 2, //Avocado Juice
"order_number" : "IT.123.78",
"qty" : 1
}
]
},
{
"qty_total" : 2,
"Orange Juice" : [
{
"id" : 1, //From id_order
"id_item" : 3, //Orange Juice
"order_number" : "IT.123.76",
"qty" : 2
}
]
},
{
"qty_total" : 1,
"Mango Juice" : [
{
"id" : 2, //From id_order
"id_item" : 5, //Mango Juice
"order_number" : "IT.123.76", //order_number Id_order 1
"qty" : 1
}
]
},
{
"qty_total" : 2,
"Ice Tea" : [
{
"id" : 1, //From id_order
"id_item" : 9, //Ice Tea
"order_number" : "IT.123.78",
"qty" : 2
}
]
},
]
Thanks for advance
You can try something like this.
const orders = [
{
"id": 1, //id_order
"order_number": "IT.123.76",
"status": "Pending",
"details": [
{
"id": 1,
"id_order": 1,
"id_item": 2, //based from this
"name": "Avocado Juice",
"qty": 7
},
{
"id": 2,
"id_order": 1,
"id_item": 3, //based from this
"name": "Orange Juice",
"qty": 2
},
{
"id": 3,
"id_order": 1,
"id_item": 5, //based from this
"name": "Mango Juice",
"qty": 1
}
]
}, {
"id": 2,
"order_number": "IT.123.78",
"status": "Pending",
"details": [
{
"id": 4,
"id_order": 2,
"id_item": 2, //based from this
"name": "Avocado Juice",
"qty": 1
},
{
"id": 5,
"id_order": 2,
"id_item": 9, //based from this
"name": "Ice Tea",
"qty": 2
}
]
}
];
var ordersById = {};
orders.forEach((order) => {
order.details.forEach((detail) => {
// ToDo: filter out completed/nonpending orders
let orderGroup;
if (!ordersById[detail.id_item]) {
orderGroup = {qty_total: detail.qty};
orderGroup[detail.name] = [{id: detail.id_order, id_item: detail.id_item, order_number: order.order_number, qty: detail.qty}];
ordersById[detail.id_item] = orderGroup;
} else {
orderGroup = ordersById[detail.id_item];
orderGroup.qty_total += detail.qty;
orderGroup[detail.name].push([{id: detail.id_order, id_item: detail.id_item, order_number: order.order_number, qty: detail.qty}]);
}
});
});
const result = Object.keys(ordersById).map((order_id) => { return ordersById[order_id];});;
console.log(result);

Mongodb how to update more than one array documents

Can somebody tell me please how to update more than one element in array?
I have object like:
{
_id: 1,
name: 'x',
someArray: [
{'a': 1},
{'a': 1, 'b': 2},
{'a': 2}
]
}
I would like to update all elements in someArray where 'a' == 1.
I tried to do it via command
db.collection.update(
{_id: 1, 'somaArray.a': 1},
{$set: {'someArray.$.c': 3}},
{multi: true}
)
but this command updated only one element in someArray. The second one is not updated. Result seems like:
{
_id: 1,
name: 'x',
someArray: [
{'a': 1, 'c': 3},
{'a': 1, 'b': 2},
{'a': 2}
]
}
How to achieve update of all elements which match the condition?
Thank you.
Try as below: (Read)
db.collection.update({_id:1},
{
$set: {
'someArray.$[elem].c': 3
}
},
{ arrayFilters: [{ "elem.a": 1 }], multi: true, "upsert": true }
)
Result response will be as below:
{
"_id" : 1,
"name" : "x",
"someArray" : [
{
"a" : 1,
"c" : 3
},
{
"a" : 1,
"b" : 2,
"c" : 3
},
{
"a" : 2
}
]
}
i think this question is similar to yours
visit (How to Update Multiple Array Elements in mongodb)! and check it out

Need to fetch values from Angular JS array

I am using a MVC model in PHP. I am getting the following string from the View layer (This is a angular.js array but I am getting it as a string):
[
{
"name" : "item",
"price" : "123",
"quantity" : 12,
"id" : 1
}, {
"name" : "hhh",
"price" : "000",
"quantity" : 12,
"id" : 2
}, {
"name" : "kk",
"price" : "88",
"quantity" : 12,
"id" : 3
}
]
How can I extract the values of name, price, quantity and id from this string and put that into insert query?
This is what is known as a serialized array, meaning that it is a JavaScript array in string form (JSON). You can use PHP's json_decode function to deserialize the string, from there you can use it as a normal array:
$json='[
{
"name" : "item",
"price" : "123",
"quantity" : 12,
"id" : 1
}, {
"name" : "hhh",
"price" : "000",
"quantity" : 12,
"id" : 2
}, {
"name" : "kk",
"price" : "88",
"quantity" : 12,
"id" : 3
}
]';
$array=json_decode($json);
foreach ($array as &$value) {
var_export($value->name);
var_export($value->price);
var_export($value->quantity);
var_export($value->id);
}
The above should display all the values in your array. I'm not sure what you mean by "put that into the insert query", but hopefully the above will help you get access to this data.

Retrieve elements using $slice

My result is following after executing find() query.
{
"_id" : ObjectId("5384928a03ea2e75268b4567"),
"0" : {
"name" : "mango",
"quantity" : "10"
},
"1" : {
"name" : "apple",
"quantity" : "14"
},
"2" : {
"name" : "banana",
"quantity" : "11"
},
"3" : {
"name" : "grapes",
"quantity" : "19"
},
"4" : {
"name" : "lichi",
"quantity" : "13"
},
"5" : {
"name" : "orange",
"quantity" : "10"
},
"6" : {
"name" : "lemon",
"quantity" : "10"
},
"7" : {
"name" : "pear",
"quantity" : "10"
},
"8" : {
"name" : "cherry",
"quantity" : "10"
},
"9" : {
"name" : "kiwi",
"quantity" : "10"
}
}
Now i want only any five elements in result(like from 2nd element to 6th element).
How to do this using $slice or is there any other method to retrieve only five elements in result?
The important thing here is, do you actually have an array for $slice to work on? There seems to be a bit of a misconception here common to people working with PHP as the way that language typically represents an array.
The mongo shell ( for example ) will show the clear distinction, where an array actually looks like this in it's JSON representation:
{
"_id" : ObjectId("5384928a03ea2e75268b4567"),
"arrayField": [
{
"name" : "mango",
"quantity" : "10"
},
{
"name" : "apple",
"quantity" : "14"
},
{
"name" : "banana",
"quantity" : "11"
},
{
"name" : "grapes",
"quantity" : "19"
}
]
}
That structure can use the $slice operator to return the elements you want. As an example here, 2 documents from index position 1
db.collection.find({},{ "arrayField": { "$slice": [ 1,2] }})
{
"_id" : ObjectId("5384928a03ea2e75268b4567"),
"arrayField" : [
{ "name" : "apple", "quantity" : "14" },
{ "name" : "banana", "quantity" : "11" }
]
}
The structure you are showing is just a bunch of key names for sub-documents within the top level document. It is probably a mistake but you just specify those fields in the projection. It's not an array so $slice does not apply:
db.collection.find({}, { "1": 1, "2": 1, "3": 1, "4": 1, "5": 1, "6": 1 })
But that probably is not what you want, so it looks like you will need to fix your data so it is an array.
$slice is used to control the number of elements in an array returned by the query, but I don't see an explicit array in your results. Your document should look something like:
{
"_id" : ObjectId("5384928a03ea2e75268b4567"),
"fruit" : [
{
"name" : "mango",
"quantity" : "10"
},
{
"name" : "apple",
"quantity" : "14"
}
]
}
Then you could query it with something like:
db.collection.find({},{"fruit": {$slice:[1:6]}})
If you want to get only 5 record from document you can use limit(), if you want to skip few of the record then use skip().
For Example :
db.collection.find().skip(2).limit(5);
This query fetch 5 documents after first 2 documents.

How to get coordinates from the Query Autocomplete? [duplicate]

This question already has an answer here:
Places Autocomplete API to get GPS coordinates from address entered
(1 answer)
Closed 8 years ago.
Suppose a very simple function to query Query Autocomplete:
$query_google_places = function ($input, array $location = null) {
$parameters = ['key' => 'AIzaSyAjCY7qYiaMv8Kkk_-D1Ha7wlRkr5neppk', 'input' => $input, 'sensor' => 'false'];
if ($location) {
$parameters['location'] = $location['lat'] . ',' . $location['lng'];
$parameters['radius'] = 10000;
}
$url = 'https://maps.googleapis.com/maps/api/place/queryautocomplete/json?' . \http_build_query($parameters);
$response = file_get_contents($url);
return $response;
};
This returns:
{
"predictions" : [
{
"description" : "Pizza Hut, Halifax, United Kingdom",
"id" : "d9274717e1e203c41287fa5936701b9584814965",
"matched_substrings" : [
{
"length" : 9,
"offset" : 0
}
],
"reference" : "CmRaAAAAyulRkdspSJ2Mr5kmlhYOC-ZT7AsKdnnwjGkFFoGHNjMWwTS5mNvQBu6FqoQ89E4U0eC-PNGN0wPD8WEYgO1if6jMmxWAqkraDFOryC8B8cWTvX333l_0UaRv_sXBIITqEhCSrz9aQB0fch-AFDS3wKG7GhTRoQw09IODWJIorqjjwCYTktkfKw",
"terms" : [
{
"offset" : 0,
"value" : "Pizza Hut"
},
{
"offset" : 11,
"value" : "Halifax"
},
{
"offset" : 20,
"value" : "United Kingdom"
}
],
"types" : [ "establishment" ]
},
{
"description" : "Pizza Hut, John William Street, Huddersfield, United Kingdom",
"id" : "a1571b1434ac1491b5f6775d9a30f8ec7798a310",
"matched_substrings" : [
{
"length" : 9,
"offset" : 0
}
],
"reference" : "CoQBdAAAADaFqqtB9NGk_v1yZdY3m6OxILfLva556GBHxHIVdPHu_R0fQCm5kCduCjKL4BgiIdoNIejet3WI7xNanaiWDpiMD1Ml7Q9EnfhypReK0N6mQIY3TxOUcmf_INhkenU3ZVL8Vk9lAxqjq5ZfxiEZk9Vv8GaEnok_OJnaRBuZdCmtEhAYs-0Qc2Zza4fLuUXIiLknGhQogPaBcUm10Y59EA5i6BWPbTNXcA",
"terms" : [
{
"offset" : 0,
"value" : "Pizza Hut"
},
{
"offset" : 11,
"value" : "John William Street"
},
{
"offset" : 32,
"value" : "Huddersfield"
},
{
"offset" : 46,
"value" : "United Kingdom"
}
],
"types" : [ "establishment" ]
},
{
"description" : "pizza hut",
"matched_substrings" : [
{
"length" : 9,
"offset" : 0
}
],
"terms" : [
{
"offset" : 0,
"value" : "pizza hut"
}
]
},
{
"description" : "Pizza Hut Delivery, Wakefield Road, Huddersfield, United Kingdom",
"id" : "0c6830de14a8e23bf971626e880201f5290ec9a6",
"matched_substrings" : [
{
"length" : 9,
"offset" : 0
}
],
"reference" : "CoQBeQAAAJnMKHhJh-IE64z6seh3sbnm4dt0h1zbMYLr4BPGCITQTZLp4lkm12HKEFw0Bt761UaZPsESrY4ha7XSXusqqRVstmRFBF2wiwF5HGMO9DhRSeIzJ8CkNvsxmlqINosGBBPUHEDQEeSOoPHn3u3MeByoLVw6AzZ9N6eTrm94hsX9EhBB9cIoXjhHjR9Tr3zBROM7GhRhpYagW9qWs9hGZ3V0o9WXfrfcXw",
"terms" : [
{
"offset" : 0,
"value" : "Pizza Hut Delivery"
},
{
"offset" : 20,
"value" : "Wakefield Road"
},
{
"offset" : 36,
"value" : "Huddersfield"
},
{
"offset" : 50,
"value" : "United Kingdom"
}
],
"types" : [ "establishment" ]
},
{
"description" : "Pizza Hut Delivery, Westgate, Halifax, United Kingdom",
"id" : "667c14a2cb5bb676bd02911e924db82fb5cbe6df",
"matched_substrings" : [
{
"length" : 9,
"offset" : 0
}
],
"reference" : "CnRtAAAAEtMYQ9N4Gmn8dpZqzHOxYGPCNP9QQ6M-gHjj2hJv2euH4gUVvDhmgazi6LcRjdYpUF41moGLr26IGc2vOPfvFg_kHTqTIYHHwiD84bu0PeEzmLzIzJw2IkGNpcW1o6weO86TW8zaUaMFZ2zNW-tynhIQFT8GvSn_q7DAoP3ytM14ExoUN3sShljpfaCWEUknvsfAjZJ_Ru4",
"terms" : [
{
"offset" : 0,
"value" : "Pizza Hut Delivery"
},
{
"offset" : 20,
"value" : "Westgate"
},
{
"offset" : 30,
"value" : "Halifax"
},
{
"offset" : 39,
"value" : "United Kingdom"
}
],
"types" : [ "establishment" ]
}
],
"status" : "OK"
}
How do I get coordinates for each result? Note, that this is server-side question.
IMO, autocompletion or query autocompletion results live in a different world than search results. Google assumes you're not supposed to need coordinates in the autocompletion list because this is not the data you will be presenting on your map or in any controller. The data you'll present will be the result of a true "search" request.
Conclusion: you're supposed to call again Google server on endpoints such as nearby search, text search or details to get the coordinates.
If you want to use details, if the user clicked on a prediction from autocomplete for example, you'll use reference attribute as a parameter of your http request to identify the clicked prediction.

Categories