Make a calculated field in mongo db - mongodb

I have two collections one is Employee and the other one is a salary. I want to make a calculated field in employee collection call monthly salary. How can I access a SALARY from Salary collection and divided by 12?
Here are some info I included in MongoDB:
db.Salary.insertMany([
{
"POSITION": "1",
"BRANCH_SIZE": "HQ",
"SALARY": "150000"
},
{
"POSITION": "2",
"BRANCH_SIZE": "HQ",
"SALARY": "100000"
},
{
"POSITION": "3",
"BRANCH_SIZE": "HQ",
"SALARY": "70000"
},
{
"POSITION": "4",
"BRANCH_SIZE": "HQ",
"SALARY": "30000"
},
{
"POSITION": "5",
"BRANCH_SIZE": "HQ",
"SALARY": "56000"
}
])
db.Employee.insertMany([
{
"EMPLOYEE_NO": "1000",
"LNAME": "Wyatt",
"FNAME": " Stefan"
"CITY": "MANKATO",
"STATE": "MN",
"ZIP": "56001",
"STATUS": "1",
"POSITION": "1"
},
{
"EMPLOYEE_NO": "1029",
"LNAME": "Martin",
"FNAME": "Edward",
"STATUS": "1",
"START_DATE": "02-MAY-95",
"END_DATE": "",
"BRANCH_NO": "103",
"BRANCH_SIZE": "MD",
"POSITION": "3"
},
{
"EMPLOYEE_NO": "1089",
"LNAME": "Stewart",
"FNAME": "Macy",
"CITY": "SAINT PAUL",
"BRANCH_NO": "101",
"BRANCH_SIZE": "BG",
"POSITION": "4"
}
])
I want to make a monthly salary for each employee. How can I do that?
Thanks in advance.
Any help would be greatly appreciated.

You can use $lookup and $divide operator to grab salary from salary collection, and divide one of the fields by 12.
Example:
db.employee.aggregate([{
$lookup: {
from: 'salary',
localField: 'POSITION',
foreignField: 'POSITION',
as: 'salary',
},
},
{
{
$project: {
dividedSalary: {
$divide: ["$salary.SALARY", 12]
}
}
}
}
])

Related

MongoDB - Can I loop through a set of rows, sum other rows based on the first rows, then update my original rows in one command?

I'm trying to figure out if I can do this query with one MongoDB update/query command, or if I going to have to write a NodeJS function to do it with 2 or 3 queries.
Given this data from my client's design:
The pseudocode would be as follows:
Find each row where type="parent"
For each row from step 1, find all the rows where row.bay=currentRow.bay and row.toSku=currentRow.toSku and type="child" and sum up the "requires" column.
Take that summed number, and update the Step 1 currentRow.requiresExtended with that sum.
When done, the "requiresExtended" column should equal the value of the "requiresExtendedDesired" (which I computed manually for a simple test case). The 5 is the sum of 2+3, the 21 is the sum of just 21, the 203 is the sum of 101+102).
I see from here: https://www.mongodb.com/docs/v4.2/tutorial/update-documents-with-aggregation-pipeline/ that we can do updates from an Aggregate Pipeline.
I'm also studying examples here: https://www.mongodb.com/community/forums/t/select-with-sub-query/115744/7
I want to add on more thought. I don't mind using multiple commands, but if I do, can I pass those multiple commands to MongoDB together and get one result back? If yes, then I'm looking at this example as well: MongoDB - simple sub query example. But then I have many questions there. Like can you have a full query under a $lookup's "from" field.
This is my really crude start at trying something like the above StackOverflow describes. I'm trying one stage at a time...
and I realized I couldn't use the localfield with the pipeline in the $lookup, so this is what I have up to now (this post helped also: Pipeline in lookup aggregation not working in mongodb)
db.NealTestBay.aggregate([
{
"$match": { type: "parent"},
},
{
"$lookup": {
"from": "NealTestBay",
"let": { "toSku": "$toSku" },
"pipeline": [
{ "$match": {
"$expr": { "$eq": [ "$toSku", "$$toSku" ] }
}}
],
"as": "grp"
}
}
])
Full test data below:
{
"RECORDS": [
{
"_id": "6336223aa11200007200678b",
"bay": "bay 1",
"requires": "0",
"requiresExtended": "0",
"requiresExtendedDesired": "5",
"sku": "",
"toSku": "Part1",
"type": "parent"
},
{
"_id": "6336223aa11200007200678c",
"bay": "bay 1",
"requires": "0",
"requiresExtended": "0",
"requiresExtendedDesired": "21",
"sku": "",
"toSku": "Part2",
"type": "parent"
},
{
"_id": "6336223aa11200007200678d",
"bay": "bay 2",
"requires": "0",
"requiresExtended": "0",
"requiresExtendedDesired": "203",
"sku": "",
"toSku": "Part1",
"type": "parent"
},
{
"_id": "6336223aa11200007200678e",
"bay": "bay 1",
"requires": "2",
"requiresExtended": "0",
"requiresExtendedDesired": "0",
"sku": "X1",
"toSku": "Part1",
"type": "child"
},
{
"_id": "6336223aa11200007200678f",
"bay": "bay 1",
"requires": "3",
"requiresExtended": "0",
"requiresExtendedDesired": "0",
"sku": "X2",
"toSku": "Part1",
"type": "child"
},
{
"_id": "6336223aa112000072006790",
"bay": "bay 2",
"requires": "101",
"requiresExtended": "0",
"requiresExtendedDesired": "0",
"sku": "X2",
"toSku": "Part1",
"type": "child"
},
{
"_id": "6336223aa112000072006792",
"bay": "bay 1",
"requires": "21",
"requiresExtended": "0",
"requiresExtendedDesired": "0",
"sku": "X4",
"toSku": "Part2",
"type": "child"
},
{
"_id": "6336223aa112000072006793",
"bay": "bay 2",
"requires": "102",
"requiresExtended": "0",
"requiresExtendedDesired": "0",
"sku": "X7",
"toSku": "Part1",
"type": "child"
}
]
}
https://mongoplayground.net/p/MOp86srCrLw
Let's try with this one:
db.collection.aggregate([
{
"$facet": {
"Parents": [
{
"$match": {
type: "parent"
}
},
{
"$addFields": {
"k1": {
"$concat": [
"$toSku",
"-",
"$bay"
]
}
}
}
],
"Children": [
{
"$match": {
type: "child"
}
},
{
"$group": {
"_id": {
"$concat": [
"$toSku",
"-",
"$bay"
]
},
"v": {
"$sum": {
"$toDouble": "$requires"
}
}
}
},
{
"$addFields": {
"k": "$_id"
}
},
{
"$project": {
"_id": 0
}
},
{
"$sort": {
k: 1
}
},
]
}
},
{
"$unwind": "$Parents"
},
{
$set: {
index: "$Parents.k1"
}
},
{
$set: {
"Parents.requiresExtended": {
"$let": {
"vars": {},
"in": {
"$let": {
"vars": {
"myVar": {
"$arrayElemAt": [
"$Children",
{
"$indexOfArray": [
"$Children.k",
"$Parents.k1"
]
}
]
}
},
"in": "$$myVar.v"
}
}
}
}
}
},
{
"$project": {
Parents: 1,
}
},
{
$project: {
"Parents.k1": 0
}
}
])
The output:
[
{
"Parents": {
"_id": "6336223aa11200007200678b",
"bay": "bay 1",
"requires": "0",
"requiresExtended": 5,
"requiresExtendedDesired": "5",
"sku": "",
"toSku": "Part1",
"type": "parent"
}
},
{
"Parents": {
"_id": "6336223aa11200007200678c",
"bay": "bay 1",
"requires": "0",
"requiresExtended": 21,
"requiresExtendedDesired": "21",
"sku": "",
"toSku": "Part2",
"type": "parent"
}
},
{
"Parents": {
"_id": "6336223aa11200007200678d",
"bay": "bay 2",
"requires": "0",
"requiresExtended": 203,
"requiresExtendedDesired": "203",
"sku": "",
"toSku": "Part1",
"type": "parent"
}
}
]

Projection on nested object mongodb find query

How to get the nested object in projection in mongodb find query.
[
{
"apikey": 1,
"meta": {
"region": {
"country": "India",
"city": "bangalore",
"pincode": 560067
},
"address": {
"houseNo": "G/C 42 Whitefield boulavourd",
"landmark": "whitefield boulavourd"
}
}
},
{
"apikey": 2,
"meta": {
"region": {
"country": "Germaany",
"city": "Munich",
"pincode": 80297
},
"address": {
"houseNo": "Zweibrückenstraße 12",
"landmark": "Zweibrückenstraße 12"
}
}
}
]
I was trying to fetch the region of apikey 2. I tried below find query
I tried find query i.e.
db.collection.find({
"apikey": "2"
},
{
"projection": {
"_id": 0,
"apikey": 1,
"meta.region": 1
}
})
I am getting error, regarding that can not do inclusion on field meta.region in exclusion projection.
Is there any other way to achieve this problem.
I want the output,
[
{
"apikey":2,
"region": {
"country": "Germaany",
"city": "Munich",
"pincode": 80297
}
}
]
This is the mongoplayground
Remove projection (wrapping) level.
db.collection.find({
apikey: 2
},
{
"_id": 1,
"apikey": "$apikey",
"region": "$meta.region"
})
Sample Mongo Playground

How to get length of sub array in mongo query

Below is the sample data:
db.infos.find()
{
"groupId": "1111",
"customerId": "A100",
"tracks": [{
"trackId": "234",
"infos": [{
"location": {
"address": "street1",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street2",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street3",
"city": "test",
"country": "US"
}
}
]
}]
}
{
"groupId": "2222",
"customerId": "A100",
"tracks": [{
"trackId": "345",
"infos": [{
"location": {
"address": "street4",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
}
]
}]
}
{
"groupId": "2222",
"customerId": "A100",
"tracks": [{
"trackId": "666",
"infos": [{
"location": {
"address": "street4",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
},
{
"location": {
"address": "street5",
"city": "test",
"country": "US"
}
}
]
}]
}
We need a query to get the length of "infos" sub array at groupId level. In the above sample data, we need the below output:
1111, 3
2222, 6
Tried below, but its not working:
db.infos.aggregate([{"$project": {"groupId": "$groupId", "samples": "$tracks.infos"}}, {"$group": {"_id": "$groupId", "samples": {"$push": "$samples"}}}, {"$project": {"_id": 1, "samples": {"$size": "$samples"}}}], { "allowDiskUse": true });
Also with large amount of data, above query is throwing an ExceededMemoryLimit exception:
2021-07-10T07:20:14.415+0000 E QUERY [js] Error: command failed: {
"ok" : 0,
"errmsg" : "$push used too much memory and cannot spill to disk. Memory limit: 104857600 bytes",
"code" : 146,
"codeName" : "ExceededMemoryLimit"
} : aggregate failed :
_getErrorWithCode#src/mongo/shell/utils.js:25:13
doassert#src/mongo/shell/assert.js:18:14
_assertCommandWorked#src/mongo/shell/assert.js:580:17
assert.commandWorked#src/mongo/shell/assert.js:673:16
DB.prototype._runAggregate#src/mongo/shell/db.js:260:9
DBCollection.prototype.aggregate#src/mongo/shell/collection.js:1074:12
#(shell):1:1
This should work with unwind:
db.collection.aggregate([
{
$unwind: "$tracks"
},
{
$group: {
"_id": "$groupId",
"count": {
"$sum": {
"$size": "$tracks.infos"
}
}
}
}
])
Even if your tracks array has more than one object this will add them up. Playground

how to get parent with child entries in mongo shell

I am new to MongoDB.
my collections are authors and books. its many to many associations
my authors collections
[{
"id": "11",
"name": "Sam",
"age": 40
},
{
"id": "12",
"name": "Jack",
"age": 20
},
{
"id": "22",
"name": "Smith",
"age": 35
}]
my books collections
[{
"id": "123",
"title": "Hello World",
"price": 200,
"authors":["Sam","Jack"]
},
{
"id": "34",
"title": "Good Day",
"price": 100,
"authors":["Smith"]
}]
This is my postman result.
[{
"authors": [
{
"id": "11",
"name": "Sam",
"age": 40,
},
{
"id": "12",
"name": "Jack",
"age": 20,
}
],
"id": "123",
"title": "Hello World",
"price": 200,
}]
I put query in mongo shell to find books but result only shown book details not shown authors(child entries).
how to I get books with authors entries in mongo shell command(like postman result).
Thanks.
Try the following code:
<db>.books.aggregate([
{
'$project': {
'id': 1,
'title': 1,
'price': 1,
'authors': 1,
'numberOfAuthors': {
'$cond': {
'if': {
'$isArray': '$authors'
},
'then': {
'$size': '$authors'
},
'else': 0
}
}
}
}, {
'$match': {
'numberOfAuthors': {
'$eq': 2
}
}
}, {
'$lookup': {
'from': 'authors',
'localField': 'authors',
'foreignField': 'name',
'as': 'authors'
}
}
])
Used projection followed by match before lookup.

Mongodb - Aggregation and Sum for each object

I need to aggregate for each "Product" object from the sales database, and sum "Price" and "Quantity" to make a product classification.
I was able to group by "Products" but I can't sum Price and Quantity to the each object.
{$group: {
_id: '$products.items',
totalprice:{$sum: "$products.items.price"},
}}
Below sample of sales database, where I need to return the sum of the "Price" and "Quantity" fields sold for each "Products".
{
"_id": {
"$oid": "5d753707c0cd851e80da914c"
},
"created_on": {
"$date": {
"$numberLong": "1567962886000"
}
},
"custumer": {
"name": "Teste",
"cep": "teste",
"address": "teste",
"district": "test",
"city": "test",
"numb": "50",
"comple": "test",
"state": "test",
"cpf": "test",
"birth": "30/09/1977",
"email": "test#gmail.com",
"phone": {
"$numberDouble": "1111111111111"
},
"gender": "M",
"portalt": {
"status": "true",
"vendor": "test",
"phone": {
"$numberDouble": "11111111111"
},
"sim": "011111111111",
"salesnumb": "1222222222222222222"
}
},
"payment": {
"method": "Boleto",
"type": "Parcelado",
"installments": "5",
"billing_date": "15"
},
**"products": {
"items": {
"5d515979736802000415a561": {
"item": {
"_id": "5d515979736802000415a561",
"name_produto": "Product 1",
"resumo": "Minutos ilimitados,20GB + 2GB",
"price": "110",
"_image": "images/test.jpg"
},
"quantity": {
"$numberInt": "2"
},
"price": {
"$numberInt": "220"
}
},
"5d515aba736802000415a562": {
"item": {
"_id": "5d515aba736802000415a562",
"name_produto": "Product 2",
"resumo": "Minutos ilimitados,3GB + 1GB",
"price": "80",
"_image": "images/test.jpg"
},
"quantity": {
"$numberInt": "1"
},
"price": {
"$numberInt": "80"
}
},
"5d515dbf736802000415a564": {
"item": {
"_id": "5d515dbf736802000415a564",
"name_produto": "Product 3",
"resumo": "Minutos ilimitados,30GB + 3GB",
"price": "150",
"_image": "images/test.jpg"
},
"quantity": {
"$numberInt": "1"
},
"price": {
"$numberInt": "150"
}
}
},**
"totalItems": {
"$numberInt": "4"
},
"totalPrice": {
"$numberInt": "450"
}
},
"seller": {
"_id": {
"$oid": "5cd086787dc59921bcad94d8"
},
"name": "test"
}
}
I need output something like:
_id:Object
5d515979736802000415a561:{sum_price: 300, sum_quantity: 30 }
5d515aba736802000415a562:{sum_price: 500, sum_quantity: 60 }
5d515dbf736802000415a564:{sum_price: 600, sum_quantity: 70 }
Thanks so much!
So let's go with the OP ask to sum the individual product price and quantity. Stripping away the other fields which are not relevant to the ask, we arrive at something like this:
var r =
[
{
_id:0,
"products": {
"items": {
"5d515979736802000415a561": {
"quantity": 2,
"price": 220,
},
"5d515aba736802000415a562": {
"quantity": 1,
"price": 80
}
}
}
}
, {
_id:1,
"products": {
"items": {
"5d515979736802000415a561": { // deliberately same id as doc above but different quantity and price
"quantity": 3,
"price": 330
},
"5d515aba736802000415a562": { // same
"quantity": 2,
"price": 160
},
"5d515979736802000415ZZZZ": { // different than above; adds "third item"
"quantity": 4,
"price": 200
}
}
}
}
];
Note that the whole inner item field is basically not important, not the least of which it only contains the unit price, not the total price (amount) and quantity per product.
"5d515dbf736802000415a564": {
"item": {
"_id": "5d515dbf736802000415a564",
// etc
So now we employ the $objectToArray to turn the keys into rvals. That gives us something we can $group on, and so here is a solution:
db.foo.aggregate([
{$project: {X: {$objectToArray: "$products.items"}}}
,{$unwind: "$X"}
,{$group: {_id: "$X.k", tot_q: {$sum:"$X.v.quantity"}, tot_amt: {$sum:"$X.v.price"}} }
]);
which given the input above yields:
{ "_id" : "5d515979736802000415ZZZZ", "tot_q" : 4, "tot_amt" : 200 }
{ "_id" : "5d515aba736802000415a562", "tot_q" : 3, "tot_amt" : 240 }
{ "_id" : "5d515979736802000415a561", "tot_q" : 5, "tot_amt" : 550 }