Sum value of elements and update field Mongo db - mongodb

How Can I sum price on array "Elemets" and set on Document field Value?
I know how to do It in sql but I,m beginner in mongo.
{
"Document": [
{
"Id": 1,
"Type": "FV",
"Number": 34521,
"Year": 2020,
"Date": "2020-01-01T00:00:00",
"Value": 27.68,
"Elements": [
{
"Id": 1,
"DocumentId": 1,
"ProductId": 1,
"Quantity": 5.00,
"Price": 17.50,
"Task": 0.23
},
{
"Id": 2,
"DocumentId": 1,
"ProductId": 2,
"Quantity": 3.00,
"Price": 24.50,
"Task": 0.23
},
]
},

If you are using MongoDB 4.2, you can use $reduce to calculate the sum in the pipeline form of update.

Related

How can I compute the income of the sellerId of the products?

I'm trying to learn the advanced mongodb+mongoose function, so this is the result of my orders, and what I'm trying to do here is to compute the total amounts related to the sellerId
So in this one, I have two documents, the document 1 have an amount of 99 and and the other one is 11
so I need to get the sum of two. I've been searching and found the aggregate, but I can't figure out how I can combine the two documents.
[
{
"_id": "6360d1d0bd860240e2589564",
"userId": "6360cf687e186ebe29ab2a29",
"products": [
{
"productId": "6360cdd166480badb8c1e05b",
"quantity": 1,
"sellerId": "6360c6ed05e1e99034b5f7eb",
"_id": "6360d1d0bd860240e2589565"
}
],
"amount": 99,
"location": "asdsad",
"time": "asdsad",
"status": "pending",
"tax": 0.99,
},
{
"_id": "6360d7978044f3048e59bf34",
"userId": "6360d50dbd860240e258c585",
"products": [
{
"productId": "6360d7528044f3048e59bb6c",
"quantity": 1,
"sellerId": "6360d4d5bd860240e258c582",
"_id": "6360d7978044f3048e59bf35"
},
{
"productId": "6360d7868044f3048e59bd8c",
"quantity": 1,
"sellerId": "6360d4d5bd860240e258c582",
"_id": "6360d7978044f3048e59bf36"
}
],
"amount": 11,
"location": "Gym",
"time": "8:00 AM",
"status": "pending",
"tax": 0.11,
}
]
This might helps.
db.collection.aggregate([
{
$group: {
_id: null,
count: {
$sum: "$amount"
}
}
}
])

MongoDB query remove bottom 10% extreme values for each specific type of data

Let's say I have a MongoDB storing transaction prices of a few products like this:
[
{
"_id": 1,
"product": "A",
"price": NumberDecimal("1.00")
},
{
"_id": 2,
"product": "A",
"price": NumberDecimal("20.00")
},
{
"_id": 3,
"product": "A",
"price": NumberDecimal("30.00")
},
{
"_id": 4,
"product": "B",
"price": NumberDecimal("10.00")
},
{
"_id": 5,
"product": "B",
"price": NumberDecimal("200.00")
},
{
"_id": 6,
"product": "B",
"price": NumberDecimal("300.00")
}
]
I want to remove bottom 10% of the extreme transaction prices, I do this:
db.collection.aggregate([
{
$bucketAuto: {
groupBy: "$price",
buckets: 10,
output: {
docs: {
$push: "$$ROOT"
}
}
}
},
{
$skip: 1
},
{
$unwind: "$docs"
},
{
$replaceWith: "$docs"
}
])
The outcome is like this:
[
{
"_id": 4,
"price": NumberDecimal("10.00"),
"product": "B"
},
{
"_id": 2,
"price": NumberDecimal("20.00"),
"product": "A"
},
{
"_id": 3,
"price": NumberDecimal("30.00"),
"product": "A"
},
{
"_id": 5,
"price": NumberDecimal("200.00"),
"product": "B"
},
{
"_id": 6,
"price": NumberDecimal("300.00"),
"product": "B"
}
]
The extreme transaction price 1.00 is removed. But I actually want the extreme 10% prices for each product to be removed, so that price 1.00 of product A is removed, and price 10.00 for product B is also removed. Expected result should be:
[
{
"_id": 2,
"price": NumberDecimal("20.00"),
"product": "A"
},
{
"_id": 3,
"price": NumberDecimal("30.00"),
"product": "A"
},
{
"_id": 5,
"price": NumberDecimal("200.00"),
"product": "B"
},
{
"_id": 6,
"price": NumberDecimal("300.00"),
"product": "B"
}
]
How can I achieve this? I have something very close but it is hard coding the product names in the query, which is very wrong:
https://mongoplayground.net/p/ur3Qmr2VJKb

How to update specific field in mongoDB given conditions?

Given the following mongdoDB structure, how can i update the field isAvailable to false given that the shopName is "jamrt" and slug is "67626dae-1537-40d8-837d-483e5759ada0". This is my query but it does not work: Shop.find({ shopName: shopName}).update({products: {$elemMatch: {slug: slug}}}, { $set: { isAvailable: req.body.isAvailable} } Thanks!
"shopName": "jmart",
"products": [{
"id": 1,
"name": "Clean and Clear Deep Clean Cleanser 100g",
"slug": "8d1c895c-6911-4fc8-a34c-89c6948233d7",
"price": 4.5,
"discount_price": 0,
"category": "Health and Beauty",
"sale": false,
"subcategory": "personal care",
"color": "black",
"article": "Clean and Clear",
"quantity": 9,
"img": "https://firebasestorage.googleapis.com/v0/b/swifty-products.appspot.com/o/Jmart%2FBeauty%2FClean%20and%20Clear%20Deep%20Clean%20Cleanser%20100g.jpg?alt=media",
"vendor": {
"id": 1,
"name": "Clean and Clear"
},
"ratings": {
"star_ratings": 0,
"votes": 0
},
"isAvailable": true
}, {
"id": 2,
"name": "Colgate Total Pro Breath Health",
"slug": "67626dae-1537-40d8-837d-483e5759ada0",
"price": 4.5,
"discount_price": 0,
"category": "Health and Beauty",
"sale": false,
"subcategory": "personal care",
"color": "black",
"article": "Colgate",
"quantity": 9,
"img": "https://firebasestorage.googleapis.com/v0/b/swifty-products.appspot.com/o/Jmart%2FBeauty%2FColgate%20Total%20Pro%20Breath%20Health.jpg?alt=media",
"vendor": {
"id": 2,
"name": "Colgate"
},
"ratings": {
"star_ratings": 0,
"votes": 0
},
"isAvailable": true
},
]
In your case, you are trying to update only the matching sub documents.
The $elemMatch operator while using in projection updates only the first matching sub document.
The $elemMatch operator while using in find updates all the fields of the matching document.
This solution might help you.
With your case, the solution might be the below in mongodb query:
db.Shop.update({"shopName":"jmart","products.slug":"67626dae-1537-40d8-837d-483e5759ada0"}, {$set: {“products.$[i].isAvailable”: false}}, {arrayFilters: [{“i.slug”: "67626dae-1537-40d8-837d-483e5759ada0"}]})

Cloudant JSON data into dashdb table joins

I have successfully imported some JSON data into cloudant, the JSON data has three levels. Then created the dashdb warehouse from cloudant to put the data into relational tables. It appears that dashdb has created three tables for each of the levels in the JSON data but has not provided me with a Key to join back to the top level. Is there a customisation that is done somewhere that tells dashdb how to join the tables.
A sample JSON doc is below:
{
"_id": "579b56388aa56fd03a4fd0a9",
"_rev": "1-698183d4326352785f213b823749b9f8",
"v": 0,
"startTime": "2016-07-29T12:48:04.204Z",
"endTime": "2016-07-29T13:11:48.962Z",
"userId": "Ranger1",
"uuid": "497568578283117a",
"modes": [
{
"startTime": "2016-07-29T12:54:22.565Z",
"endTime": "2016-07-29T12:54:49.894Z",
"name": "bicycle",
"_id": "579b56388aa56fd03a4fd0b1",
"locations": []
},
{
"startTime": "2016-07-29T12:48:02.477Z",
"endTime": "2016-07-29T12:53:28.503Z",
"name": "walk",
"_id": "579b56388aa56fd03a4fd0ad",
"locations": [
{
"at": "2016-07-29T12:49:05.716Z",
"_id": "579b56388aa56fd03a4fd0b0",
"location": {
"coords": {
"latitude": -34.0418308,
"longitude": 18.3503616,
"accuracy": 37.5,
"speed": 0,
"heading": 0,
"altitude": 0
},
"battery": {
"is_charging": true,
"level": 0.7799999713897705
}
}
},
{
"at": "2016-07-29T12:49:48.488Z",
"_id": "579b56388aa56fd03a4fd0af",
"location": {
"coords": {
"latitude": -34.0418718,
"longitude": 18.3503895,
"accuracy": 33,
"speed": 0,
"heading": 0,
"altitude": 0
},
"battery": {
"is_charging": true,
"level": 0.7799999713897705
}
}
},
{
"at": "2016-07-29T12:50:20.760Z",
"_id": "579b56388aa56fd03a4fd0ae",
"location": {
"coords": {
"latitude": -34.0418788,
"longitude": 18.3503887,
"accuracy": 33,
"speed": 0,
"heading": 0,
"altitude": 0
},
"battery": {
"is_charging": true,
"level": 0.7799999713897705
}
}
}
]
},
{
"startTime": "2016-07-29T12:53:37.137Z",
"endTime": "2016-07-29T12:54:18.505Z",
"name": "carshare",
"_id": "579b56388aa56fd03a4fd0ac",
"locations": []
},
{
"startTime": "2016-07-29T12:54:54.112Z",
"endTime": "2016-07-29T13:11:47.818Z",
"name": "bus",
"_id": "579b56388aa56fd03a4fd0aa",
"locations": [
{
"at": "2016-07-29T13:00:08.039Z",
"_id": "579b56388aa56fd03a4fd0ab",
"location": {
"coords": {
"latitude": -34.0418319,
"longitude": 18.3503623,
"accuracy": 36,
"speed": 0,
"heading": 0,
"altitude": 0
},
"battery": {
"is_charging": false,
"level": 0.800000011920929
}
}
}
]
}
]
}
SQL for the three tables created in dashdb showing all the fields in each table is here. Note there is no FK that I can see, the "_ID" fields are unique to each table.
SELECT ENDTIME,STARTTIME,USERID,UUID,V,"_ID","_REV"
FROM <schemaname>.RANGER_DATA
where "_ID" = '579b56388aa56fd03a4fd0a9'
SELECT ARRAY_INDEX,ENDTIME,NAME,STARTTIME,TOTALPAUSEDMS,"_ID"
FROM <schemaname>.RANGER_DATA_MODES
where "_ID" = '579b56388aa56fd03a4fd0b1'
SELECT ARRAY_INDEX,AT,LOCATION_BATTERY_IS_CHARGING,LOCATION_BATTERY_LEVEL,LOCATION_COORDS_ACCURACY,LOCATION_COORDS_ALTITUDE,LOCATION_COORDS_HEADING,LOCATION_COORDS_LATITUDE,LOCATION_COORDS_LONGITUDE,LOCATION_COORDS_SPEED,RANGER_DATA_MODES,"_ID"
FROM <schemaname>.RANGER_DATA_MODES_LOCATIONS
where "_ID" = '579b56388aa56fd03a4fd0b0'
Cloudant uses _id for its UID for each document. It seems that the warehousing task iterates over these documents and assumes that there is a new document every time it sees a new _id.
Because you're using _id in your modes and locations this will produce an undesired result in the SQL DB.
Renaming your _id in modes and locations to something else should fix the problem.

Finding documents that are valid on a specific date

I have some data stored in a mongodb collection similar to:
{"_id": 1, "category": "food", "name": "chips", "price": 1.50, "effectiveDate": ISODate("2013-03-01T07:00:00Z")}
{"_id": 2, "category": "food", "name": "chips", "price": 1.75, "effectiveDate": ISODate("2013-03-05T07:00:00Z")}
{"_id": 3, "category": "food", "name": "chips", "price": 1.90, "effectiveDate": ISODate("2013-03-10T07:00:00Z")}
{"_id": 4, "category": "beverage", "name": "pop", "price": 2.00, "effectiveDate": ISODate("2013-03-01T07:00:00Z")}
{"_id": 5, "category": "beverage", "name": "pop", "price": 2.25, "effectiveDate": ISODate("2013-03-05T07:00:00Z")}
{"_id": 6, "category": "beverage", "name": "pop", "price": 1.80, "effectiveDate": ISODate("2013-03-10T07:00:00Z")}
In mongodb, how would I go about writing a query that would return the documents that were active on a specific date, grouped by the category?
If I specified March 6, 2013 I'd expect to see the results:
{"_id": 2, "category": "food", "name": "chips", "price": 1.75, "effectiveDate": ISODate("2013-03-05T07:00:00Z")}
{"_id": 5, "category": "beverage", "name": "pop", "price": 2.25, "effectiveDate": ISODate("2013-03-05T07:00:00Z")}
I am new to mongo and have been trying to do this using group, aggregate and mapreduce but have been just spinning in circles.
To give you a real good answer, I need more details of your code and what you are trying to do. But if I understand right, I think you can solve that using only the aggregation framework. You should know that the aggregation framework uses the pipeline concept, in other words, the result of each step is used as the entry to the following.
My query:
db.yourcollection.aggregate([
/* First exclude everything that is superior to a given date */
{$match:{effectiveDate:{$lte:new Date(2013,2,6)}}},
/* Sort the rest by date, descending */
{$sort:{effectiveDate:-1}},
/* Group by name+category and grab only the first result
(the newest below that date) */
{$group:{_id:{name:'$name',category:'$category'}, effectiveDate:{$first:"$effectiveDate"},price:{$first:"$price"}}},
/* You said you want the results grouped by category.
This last $group does that and returns all matching products inside an array
It also removes the duplicates */
{$group:{_id:'$_id.category',products:{$addToSet:{name:"$_id.name",price:"$price",effectiveDate:"$effectiveDate"}}}}
])
The output is like this:
{
"result": [
{
"_id": "food",
"products": [
{
"name" : "chips",
"price" : 1.75,
"effectiveDate" : ISODate("2013-03-05T07:00:00Z")
}
]
},
{
"_id" : "beverage",
"products": [
{
"name" : "pop",
"price" : 2.25,
"effectiveDate" : ISODate("2013-03-05T07:00:00Z")
}
]
}
],
"ok":1
}
You can change the final output modifing the last $group or using a $project