I have a 2 collection
1.transactions:
id:Account1,
type of transaction:[credit or debit],
amount:some currency
date:Date
accounts:
name:Account 1 or so on
openingBalance:some amount
another collection of accounts has opening balance
/* 1 */
{
"_id" : ObjectId("5f214de9d150a21db8095395"),
"name" : "Account 2",
"openingBalance" : 10000.0
}
/* 2 */
{
"_id" : ObjectId("5f214de9d150a21db8095396"),
"name" : "Account 1",
"openingBalance" : 50000.0
}
and another collection has all the transaction by amount and by nature of transaction
/* 1 */
{
"_id" : ObjectId("5f214cf7608157bae3aeb41a"),
"Account" : "Account 1",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-01-04T13:18:43.000Z")
}
/* 2 */
{
"_id" : ObjectId("5f214d01608157bae3aeb41d"),
"Account" : "Account 1",
"NatureOfTranscation" : "debit",
"Amount" : 140,
"Date" : ISODate("2019-12-03T22:30:25.000Z")
}
/* 3 */
{
"_id" : ObjectId("5f214d0b608157bae3aeb422"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-03-24T09:15:12.000Z")
}
/* 4 */
{
"_id" : ObjectId("5f214d14608157bae3aeb425"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-03-13T09:37:13.000Z")
}
/* 5 */
{
"_id" : ObjectId("5f214d1d608157bae3aeb42a"),
"Account" : "Account 1",
"NatureOfTranscation" : "debit",
"Amount" : 140,
"Date" : ISODate("2020-04-26T02:18:39.000Z")
}
/* 6 */
{
"_id" : ObjectId("5f214d28608157bae3aeb431"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-06-26T03:07:19.000Z")
}
/* 7 */
{
"_id" : ObjectId("5f214d33608157bae3aeb436"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-06-22T12:18:13.000Z")
}
Now using aggregation
Sort by Date
Group by Account
if it is credit openingbalance + amount will be closing balance for that document and vice versa
I have tried this
db.getCollection('col').aggregate([
{
$sort: { 'Date': 1}
},
{
$group: {
_id: '$Account',
transactions: {
$push: '$$ROOT'
}
}
},
{
$project: {
id: 1,
transactions:1,
count: 1
}
}
])
So Far i have got this.
/* 1 */
{
"_id" : "Account 1",
"transactions" : [
{
"_id" : ObjectId("5f214d01608157bae3aeb41d"),
"Account" : "Account 1",
"NatureOfTranscation" : "debit",
"Amount" : 140,
"Date" : ISODate("2019-12-03T22:30:25.000Z")
},
{
"_id" : ObjectId("5f214cf7608157bae3aeb41a"),
"Account" : "Account 1",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-01-04T13:18:43.000Z")
},
{
"_id" : ObjectId("5f214d1d608157bae3aeb42a"),
"Account" : "Account 1",
"NatureOfTranscation" : "debit",
"Amount" : 140,
"Date" : ISODate("2020-04-26T02:18:39.000Z")
}
]
}
/* 2 */
{
"_id" : "Account 2",
"transactions" : [
{
"_id" : ObjectId("5f214d14608157bae3aeb425"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-03-13T09:37:13.000Z")
},
{
"_id" : ObjectId("5f214d0b608157bae3aeb422"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-03-24T09:15:12.000Z")
},
{
"_id" : ObjectId("5f214d33608157bae3aeb436"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-06-22T12:18:13.000Z")
},
{
"_id" : ObjectId("5f214d28608157bae3aeb431"),
"Account" : "Account 2",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-06-26T03:07:19.000Z")
}
]
}
Desired result:
{
"_id" : "Account 1",
"transactions" : [
{
"_id" : ObjectId("5f214d01608157bae3aeb41d"),
"Account" : "Account 1",
"NatureOfTranscation" : "debit",
"Amount" : 140,
"Date" : ISODate("2019-12-03T22:30:25.000Z"),
"closingBalance":49860
},
{
"_id" : ObjectId("5f214cf7608157bae3aeb41a"),
"Account" : "Account 1",
"NatureOfTranscation" : "credit",
"Amount" : 140,
"Date" : ISODate("2020-01-04T13:18:43.000Z"),
"closingBalance":50000
},
{
"_id" : ObjectId("5f214d1d608157bae3aeb42a"),
"Account" : "Account 1",
"NatureOfTranscation" : "debit",
"Amount" : 140,
"Date" : ISODate("2020-04-26T02:18:39.000Z"),
"closingBalance":49500
}
]
}
Any suggestion of regarding the database model also will be welcome.
Thanks In advance.
Related
I have a problem with update object nested in array ("companyBases"), because update scripts overwrites my nested object, i have the following model:
{
"_id" : ObjectId("5d6504541be1e64145c20c66"),
"margin" : 10,
"defaultDeprication" : 10,
"companyBases" : [
{
"_id" : ObjectId("5d6504541be1e64145c20c64"),
"name" : "Tech Parking 2",
"street" : "Traktat Ojca",
"postalCode" : "30-856",
"city" : "Cracow",
"location" : {
"lng" : 50.036017,
"lat" : 20.086752
},
"__v" : 0
},
{
"_id" : ObjectId("5d6504541be1e64145c20c65"),
"name" : "Tech Parking 3",
"street" : "ul.Bieżanowska 258B",
"postalCode" : "30-856",
"city" : "Cracow",
"location" : {
"lng" : 50.01744,
"lat" : 20.033522
},
"__v" : 0
}
],
}
I'am executing update query:
db.companies.updateOne(
{
_id: ObjectId("5d6504541be1e64145c20c66"),
"companyBases._id": ObjectId("5d6504541be1e64145c20c64")
},
{
$set: {
"companyBases.$": {
"street" : "ul.Małapolska 123"
}
}
}
)
But it overwrites my nested object and now it looking like this:
{
"_id" : ObjectId("5d6504541be1e64145c20c66"),
"margin" : 10,
"defaultDeprication" : 10,
"companyBases" : [
{
"street" : "ul.Małapolska 123"
},
{
"_id" : ObjectId("5d6504541be1e64145c20c65"),
"name" : "Tech Parking 3",
"street" : "ul.Bieżanowska 258B",
"postalCode" : "30-856",
"city" : "Cracow",
"location" : {
"lng" : 50.01744,
"lat" : 20.033522
},
"__v" : 0
}
],
}
I would like to rewrite all field from nested object and update fields that i choose in update query.
It should looks like this (without overwriting whole object):
{
"_id" : ObjectId("5d6504541be1e64145c20c66"),
"margin" : 10,
"defaultDeprication" : 10,
"companyBases" : [
{
"_id" : ObjectId("5d6504541be1e64145c20c64"),
"name" : "Tech Parking 2",
"street" : "ul.Małapolska 123",
"postalCode" : "30-856",
"city" : "Cracow",
"location" : {
"lng" : 50.036017,
"lat" : 20.086752
},
"__v" : 0
},
{
"_id" : ObjectId("5d6504541be1e64145c20c65"),
"name" : "Tech Parking 3",
"street" : "ul.Bieżanowska 258B",
"postalCode" : "30-856",
"city" : "Cracow",
"location" : {
"lng" : 50.01744,
"lat" : 20.033522
},
"__v" : 0
}
],
}
You should use arrayFilter in the update operation, as described here:
positinal filter for arrays
db.companies.updateOne(
{
_id: ObjectId("5d6504541be1e64145c20c66"),
},
{
$set: {
"companyBases.$[element].street: "ul.Małapolska 123"
}
},
{
arrayFilters: [ {"element._id": ObjectId("5d6504541be1e64145c20c64")} ]
}
)
I have 2 tables for now, 1) material master another is 2)forcast table.
localField is Material, foreignField is MATERIAL. For a single material there are multiple entry on forcast table for each month. Now I need monthly, yearly, and current quarter sum from forcast table for a meterial.
But unable to get multiple sum(yearly, monthly).
db.material_master.aggregate(
[
{
"$lookup" : {
"from" : "monthly_forcast_table",
"localField" : "Material",
"foreignField" : "MATERIAL",
"as" : "forcast"
}
},
{
"$unwind" : {
"path" : "$forcast",
"preserveNullAndEmptyArrays" : true
}
},
{
"$match" : {
"forcast.EMPLOYEE CODE" : "47000006"
}
},
{
"$group" : {
"_id" : {
"$cond" : [
{
"Financial Year" : "2016-2107"
},
{
"$sum" : "$forcast.Qty"
},
0.0
]
}
}
}
],
{
"allowDiskUse" : true
}
);
Data
material master
{
"_id" : ObjectId("5affd515415668486654f95e"),
"Focus Code" : "RMTEC0049",
"Material" : "100000000",
"Material type" : "ZROH",
"Brand code" : "1003",
"Brand name" : "Raw Material",
"Old Material Number" : "RMTEC0049",
"Material description" : "Tech Hexaconazole"
}
{
"_id" : ObjectId("5affd515415668486654f95f"),
"Focus Code" : "RMEMF0103-2",
"Material" : "100000001",
"Material type" : "ZROH",
"Brand code" : "1002",
"Brand name" : "Raw Material",
"Old Material Number" : "RMEMF0103-2",
"Material description" : "MEGASOLVE ESBO"
}
and forcust
{
"_id" : ObjectId("5affaa3e6f8be823dea6f1b0"),
"PRICE" : 0.0,
"STATE" : "GJ",
"REGION" : "GJ-NS",
"DEPOT" : "AHMEDABAD",
"EMPLOYEE CODE" : "47000006",
"EMPLOYEE NAME" : "GJ Jignesh",
"CATEGORY" : "NUCLEUS",
"BRAND" : "BRAND",
"PRODUCT NAME" : "BRAND ( L ) - 1 Ltr",
"PRODUCT CODE" : "FGMNL1041",
"MATERIAL" : "810000088",
"Financial Year" : "2015-2016",
"Month" : "2015-04-01",
"Qty" : 0.0
}
{
"_id" : ObjectId("5affaa3e6f8be823dea6f1b1"),
"PRICE" : 0.0,
"STATE" : "GJ",
"REGION" : "GJ-NS",
"DEPOT" : "AHMEDABAD",
"EMPLOYEE CODE" : "47000006",
"EMPLOYEE NAME" : "GJ Jignesh",
"CATEGORY" : "NUCLEUS",
"BRAND" : "BRAND",
"PRODUCT NAME" : "BRAND ( L ) -500 ML",
"PRODUCT CODE" : "FGMNL0007",
"MATERIAL" : "810000095",
"Financial Year" : "2015-2016",
"Month" : "2015-04-01",
"Qty" : 0.0
}
{
"_id" : ObjectId("5affaa3e6f8be823dea6f1b2"),
"PRICE" : 15.0,
"STATE" : "GJ",
"REGION" : "GJ-NS",
"DEPOT" : "AHMEDABAD",
"EMPLOYEE CODE" : "47000006",
"EMPLOYEE NAME" : "GJ Jignesh",
"CATEGORY" : "NUCLEUS",
"BRAND" : "BRAND",
"PRODUCT NAME" : "BRAND ( L ) -250 ML",
"PRODUCT CODE" : "FGMNL0008",
"MATERIAL" : "810000094",
"Financial Year" : "2015-2016",
"Month" : "2015-04-01",
"Qty" : 15.0
}
Expected output:
Yearly sum: Qty sum for "Financial Year" : "2015-2016"
last 3 month sum : "Month" : "2015-04-01","2015-05-01","2015-06-01"
last 1 month sum : "Month" : "2015-06-01"
I have used $lookup in my aggregate query.
But as I am seeing it works as LEFT OUTER JOIN.
I want to fetch exact matches document(INNER JOIN) with $lookup.
Is there any way to get it done?
This is my inventory collection:
/* 1 */
{
"_id" : 1,
"sku" : "abc",
"description" : "product 1",
"instock" : 120
}
/* 2 */
{
"_id" : 2,
"sku" : "def",
"description" : "product 2",
"instock" : 80
}
/* 3 */
{
"_id" : 3,
"sku" : "ijk",
"description" : "product 3",
"instock" : 60
}
/* 4 */
{
"_id" : 4,
"sku" : "jkl",
"description" : "product 4",
"instock" : 70
}
/* 5 */
{
"_id" : 5,
"sku" : null,
"description" : "Incomplete"
}
This is my orders collection
/* 1 */
{
"_id" : 1,
"item" : "abc",
"price" : 12,
"quantity" : 2
}
/* 2 */
{
"_id" : 2,
"item" : "jkl",
"price" : 20,
"quantity" : 1
}
/* 3 */
{
"_id" : 10,
"item" : "jklw",
"price" : 20,
"quantity" : 1
}
And this is query
db.getCollection('inventory').aggregate([
{
$lookup:
{
from: "orders",
localField: "sku",
foreignField: "item",
as: "inventory_docs"
}
}
])
In this query I am getting all the inventory's document matches with orders documents
Expected Result
/* 1 */
{
"_id" : 1,
"sku" : "abc",
"description" : "product 1",
"instock" : 120,
"inventory_docs" : [
{
"_id" : 1,
"item" : "abc",
"price" : 12,
"quantity" : 2
}
]
}
/* 2 */
{
"_id" : 4,
"sku" : "jkl",
"description" : "product 4",
"instock" : 70,
"inventory_docs" : [
{
"_id" : 2,
"item" : "jkl",
"price" : 20,
"quantity" : 1
}
]
}
Just add the $match pipeline stage which skips documents with empty inventory_docs field. There no other way to achieve that.
Query:
db.getCollection('inventory').aggregate([
{
$lookup: {
from: "orders",
localField: "sku",
foreignField: "item",
as: "inventory_docs"
}
},
{
$match: {
"inventory_docs": {$ne: []}
}
}
])
Result:
{
"_id" : 1.0,
"sku" : "abc",
"description" : "product 1",
"instock" : 120.0,
"inventory_docs" : [
{
"_id" : 1.0,
"item" : "abc",
"price" : 12.0,
"quantity" : 2.0
}
]
}
{
"_id" : 4.0,
"sku" : "jkl",
"description" : "product 4",
"instock" : 70.0,
"inventory_docs" : [
{
"_id" : 2.0,
"item" : "jkl",
"price" : 20.0,
"quantity" : 1.0
}
]
}
Suppose I have 2 documents and I want to make join.
customers document
/* 1 */
{
"_id" : ObjectId("596d5aacb02f922a92475698"),
"code" : "A001",
"name" : "NameA001",
"age" : 35
}
/* 2 */
{
"_id" : ObjectId("596d5aacb02f922a9247569a"),
"code" : "A002",
"name" : "NameA002",
"age" : 52
}
/* 3 */
{
"_id" : ObjectId("596d5aacb02f922a9247569c"),
"code" : "A003",
"name" : "NameA003",
"age" : 47
}
sale document
/* 1 */
{
"_id" : ObjectId("596d5ad3b02f922a924756c3"),
"ucode" : "SL-A001",
"pname" : "Product 1",
"quantity" : 3
}
/* 2 */
{
"_id" : ObjectId("596d5ad3b02f922a924756c5"),
"ucode" : "SL-A001",
"pname" : "Product 2",
"quantity" : 5
}
/* 3 */
{
"_id" : ObjectId("596d5ad3b02f922a924756cd"),
"ucode" : "SL-A002",
"pname" : "Product 3",
"quantity" : 10
}
/* 4 */
{
"_id" : ObjectId("596d5ad3b02f922a924756d1"),
"ucode" : "SL-A003",
"pname" : "Product 8",
"quantity" : 5
}
I want to make join on customers and sale document to get all customers whose age are less than 50. The result looks like
/* 1 */
{
"_id" : ObjectId("596d5aacb02f922a92475698"),
"code" : "A001",
"name" : "NameA001",
"age" : 35,
"history" : [
{
"_id" : ObjectId("596d5ad3b02f922a924756c3"),
"ucode" : "SL-A001",
"pname" : "Product 1",
"quantity" : 3
},
{
"_id" : ObjectId("596d5ad3b02f922a924756c5"),
"ucode" : "SL-A001",
"pname" : "Product 2",
"quantity" : 5
}
]
}
/* 2 */
{
"_id" : ObjectId("596d5aacb02f922a9247569c"),
"code" : "A003",
"name" : "NameA003",
"age" : 47,
"history" : [
{
"_id" : ObjectId("596d5ad3b02f922a924756d1"),
"ucode" : "SL-A003",
"pname" : "Product 8",
"quantity" : 5
}
]
}
I wrote aggregate statement but I dont know how to make LIKE condition on $lookup.
db.customer.aggregate([
{
$match: { "age": { $lt: 50 } }
},
{
$lookup:
{
from: "sale",
localField: "code",
foreignField: "ucode",
as: "history"
}
}
])
How can I write lookup with Like condition on localField or foreignField? (Or any suggestion to join with like condition)
Thank you in advance.
I am having trouble with the $group stage in my aggregation. I want to group all the "recentPlays.quiz" values together and count the repeated values, so the end result I want from the aggregation is two fields: the quiz object and the total. In this case it would be something like:
{
"recentPlays" : [
{
"quiz" : {
"author" : "red-tester1",
"title" : "Asdffff Dfasdf"
},
"count": 1
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Creation Test 2"
},
"count": 1
},
{
"quiz" : {
"author" : "blue-tester1",
"title" : "Finky Fink"
},
"count": 4
}
]
}
Here is the aggregation I have so far:
db.users.aggregate([
{$match: { "recentPlays.date": {$gte:twentyFourHrsAgo}}},
{$project: {"recentPlays.quiz":1, _id:0}}
]).pretty();
Here is that aggregation's output:
MongoDB shell version: 3.2.1
connecting to: videoQuiz
{
"recentPlays" : [
{
"quiz" : {
"author" : "red-tester1",
"title" : "Asdffff Dfasdf"
}
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Creation Test 2"
}
},
{
"quiz" : {
"author" : "blue-tester1",
"title" : "Finky Fink"
}
},
{
"quiz" : {
"author" : "blue-tester1",
"title" : "Finky Fink"
}
},
{
"quiz" : {
"author" : "blue-tester1",
"title" : "Finky Fink"
}
},
{
"quiz" : {
"author" : "blue-tester1",
"title" : "Finky Fink"
}
}
]
}
Here is the entire collection:
MongoDB shell version: 3.2.1
connecting to: videoQuiz
{
"_id" : ObjectId("580f7be62c6fd3c8065577f5"),
"user" : "blue-tester1",
"email" : "aslfjjcc#lkcjasdc.com",
"createdAt" : ISODate("2016-10-25T15:36:06.933Z"),
"recentPlays" : [
{
"quiz" : {
"author" : "red-tester1",
"title" : "Asdffff Dfasdf"
},
"score" : "0",
"date" : ISODate("2016-10-25T15:36:27.546Z")
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Creation Test 2"
},
"score" : "100",
"date" : ISODate("2016-10-25T15:37:09.142Z")
}
],
"mostRecentQuiz" : {
"author" : "red-tester3",
"title" : "Creation Test 2"
},
"mostRecentQuizTime" : ISODate("2016-10-25T15:37:09.142Z"),
"plays" : 2
}
{
"_id" : ObjectId("580a5dea650296d808082e65"),
"user" : "red-tester3",
"email" : "aldkdk#ccc.com",
"createdAt" : ISODate("2016-10-21T18:26:50.870Z"),
"recentPlays" : [
{
"quiz" : {
"author" : "red-tester2",
"title" : "TOP PLAYED QUIZ - Today"
},
"score" : "0",
"date" : ISODate("2016-10-21T18:27:16.292Z")
},
{
"quiz" : {
"author" : "red-tester2",
"title" : "TOP LIKED QUIZ - TODAY"
},
"score" : "100",
"date" : ISODate("2016-10-21T18:27:32.788Z")
},
{
"quiz" : {
"author" : "red-tester2",
"title" : "TOP LIKED QUIZ - TODAY"
},
"score" : "100",
"date" : ISODate("2016-10-21T18:27:44.497Z")
},
{
"quiz" : {
"author" : "Bertram",
"title" : "frfrf"
},
"score" : "100",
"date" : ISODate("2016-10-21T18:28:43.893Z")
},
{
"quiz" : {
"author" : "Bertram",
"title" : "Here We Go With the New Thing"
},
"score" : "0",
"date" : ISODate("2016-10-21T18:43:51.205Z")
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Presidents of the United States"
},
"score" : "0",
"date" : ISODate("2016-10-23T00:53:29.167Z")
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Presidents of the United States"
},
"score" : "0",
"date" : ISODate("2016-10-23T00:53:44.815Z")
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Creation Test 1"
},
"score" : "100",
"date" : ISODate("2016-10-23T23:50:55.355Z")
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Creation Test 2"
},
"score" : "100",
"date" : ISODate("2016-10-23T23:52:33.210Z")
},
{
"quiz" : {
"author" : "red-tester3",
"title" : "Here Is a New Title"
},
"score" : "100",
"date" : ISODate("2016-10-23T23:58:53.683Z")
}
],
"mostRecentQuiz" : {
"author" : "red-tester3",
"title" : "Here Is a New Title"
},
"mostRecentQuizTime" : ISODate("2016-10-23T23:58:53.683Z"),
"plays" : 10,
"likedQuizzes" : [
{
"title" : "TOP LIKED QUIZ - TODAY",
"author" : "red-tester2",
"date" : ISODate("2016-10-21T18:27:34.893Z")
},
{
"title" : "frfrf",
"author" : "Bertram",
"date" : ISODate("2016-10-21T18:28:45.863Z")
},
{
"title" : "Here We Go With the New Thing",
"author" : "Bertram",
"date" : ISODate("2016-10-21T18:43:53.148Z")
}
],
"createdQuizzes" : [
{
"title" : "Yeah Here We Go",
"id" : ObjectId("580a63f274b9a89c061f973e")
},
{
"title" : "Z Alpha",
"id" : ObjectId("580a641474b9a89c061f973f")
},
{
"title" : "Tags Limit Test",
"id" : ObjectId("580a6bda8d8049ac0bc1df2e")
},
{
"title" : "Tags Limit test2",
"id" : ObjectId("580a6bf98d8049ac0bc1df2f")
},
{
"title" : "Presidents of the United States",
"id" : ObjectId("580c09d28d8049ac0bc1df30")
},
{
"title" : "Creation Test 1",
"id" : ObjectId("580d4cca8d8049ac0bc1df31")
},
{
"title" : "Creation Test 2",
"id" : ObjectId("580d4d2d8d8049ac0bc1df32")
},
{
"title" : "Here Is a New Title",
"id" : ObjectId("580d4ead8d8049ac0bc1df33")
}
]
}
Thanks in advance for any guidance. Please excuse the dummy text in these documents, it is for testing purposes only.
This will be a two step process. The first step is to $unwind the "recentPlays" array. The second step is to $group by "recentPlays.quiz".
For example:
db.users.aggregate([
{ "$match" : { "recentPlays.date": { "$gte" : twentyFourHrsAgo}}},
{ "$project" : {"recentPlays.quiz":1, _id:0}},
{ "$unwind" : "$recentPlays" },
{ "$group" : { "_id" : "$recentPlays.quiz", "total" : { "$sum" : 1 } } }
]).pretty();