I have 2 sql queries . These 2 queries results should be combined within one mongodb aggregation.
1st Query:
SELECT id,sum(DiscCount) as UTVCount from (SELECT edu.dispositionBy as id ,count() as DiscCount. FROM `HRC_Education` edu WHERE edu.`RecommendedDisposition` = 'Edu.Disposition.UTV' AND edu.dispositionBy in "users" AND date(edu.DispositionDate) between "2022-01-12T00:00:00.0Z" AND "2022-01-23T00:00:00.0Z" group by id)
union
(SELECT emp.dispositionBy as id ,count() as DiscCount FROM `HRC_Employment` emp WHERE emp.`RecommendedDisposition` = 'Emp.Disposition.UTV' AND emp.dispositionBy in "users" AND date(emp.DispositionDate) between "2022-01-12T00:00:00.0Z" AND "2022-01-23T00:00:00.0Z" group by id)
2nd query:
SELECT id,sum(DiscCount) as UTVCount from (SELECT edu.dispositionBy as id ,count() as DiscCount. FROM `HRC_Education` edu WHERE edu.`RecommendedDisposition` = 'Edu.Disposition.UTV' AND date(edu.DispositionDate) between "2022-01-12T00:00:00.0Z" AND "2022-01-23T00:00:00.0Z" group by id)
union
(SELECT emp.dispositionBy as id ,count() as DiscCount FROM `HRC_Employment` emp WHERE emp.`RecommendedDisposition` = 'Emp.Disposition.UTV' AND date(emp.DispositionDate) between "2022-01-12T00:00:00.0Z" AND "2022-01-23T00:00:00.0Z" group by id)
My Mongo Query:
const result = HRC_Education
.aggregate([
{
$match: {
DispositionDate: { $gte: new Date("2022-01-12T00:00:00.0Z"), $lt: new Date("2022-01-23T00:00:00.0Z") },
DispositionBy: { $eq: 'users' },
RecommendedDisposition: { $eq: 'Edu.Disposition.UTV' }
}
},
{
$unionWith: {
coll: "HRC_Employment",
pipeline: [
{
$match: {
DispositionDate: { $gte: new Date("2022-01-12T00:00:00.0Z"), $lt: new Date("2022-01-23T00:00:00.0Z") },
DispositionBy: { $eq: 'users' },
RecommendedDisposition: { $eq: 'Emp.Disposition.UTV' }
}
}
]
}
},
{
$group: {
_id: {
id: "$DispositionBy"
},
total: { $sum: 1 }
}
},
{
$project: {
_id:0,
id: "$_id.id",
UTVCount: "$total"
}
}
])
Sample records for HRC_Education:
[{DispositionDate: 2022-01-14T00:00:00.0Z,DispositionBy:'users',RecommendedDisposition: 'Edu.Disposition.UTV' }]
Sample records for HRC_Employment:
[{DispositionDate: 2022-01-14T00:00:00.0Z,DispositionBy:'users',RecommendedDisposition: 'Emp.Disposition.UTV' }]
With my mongo Query, I am able to convert either 1st query result or 2nd second result but not both. Can anyone please help me on this to combine these both sql queries into one mongo aggregation.
Related
I'm an experienced SQL user, but am an absolute MongoDB/JSON newbie. I'm trying to aggregate results from a couple collections in our database here and keep running into this error: uncaught exception: SyntaxError: missing : after property id :
This is the script I'm using:
db.transactions.aggregate([
{
$match:
{
$and:
[
{
"updated_at": { $gte: ISODate("2022-01-01") }
},
{
"updated_at": { $lte: ISODate("2022-03-31") }
},
]
}
},
{
$lookup:
{
from: 'clients',
localField: 'client',
foreignField: '_id',
as: 'clients'
}
},
{
$unwind: '$clients'
},
{
$addFields:
{
"client_name": "$clients.client_name"
,"client_label": "$clients.client_label"
,"client_code": "$clients.client_code"
,"client_country": "$clients.client_country"
,"client_base_currency": "$clients.client_base_currency"
,"client_invoice_currency": "$clients.client_invoice_currency"
}
},
{
$project:
{
client_name: 1
,client_label: 1
,client_code: 1
,client_country: 1
,client_base_currency: 1
,client_invoice_currency: 1
,updated_at: 1
,usd_value: 1
}
},
{
$group:
{
_id:
{ $dateToString: { "date": "$updated_at", "format": "%Y-%m" } }
,"$client_name"
,"$client_label"
,"$client_code"
,"$client_country"
,"$client_base_currency"
,"$client_invoice_currency"
,total_vol: { $sum: "$usd_value" }
}
}
])
With some Googling I've been able to put together this script, but now I'm getting stuck. I'm sure it's happening in the $group stage, as when I comment out that whole part, the query works fine.
I'm basically trying to get the equivalent of this SQL script:
select
(extract(year from t.updated_at) * 100 + extract(month from t.updated_at)) as year_month
,c.client_name
,c.client_label
,c.client_code
,c.client_country
,c.client_base_currency
,c.client_invoice_currency
,sum(t.usd_value) as total_vol
from transactions t
left join clients c
on t.client = c._id
where t.update_at between '2022-01-01' and '2022-03-31'
group by 1,2,3,4,5,6,7
Any suggestions on how to correctly do this? I know this is fairly basic, but it's not entirely clicking yet, the whole JSON syntax.
I have two collections in my MongoDB employee and employeeData i need to get some statics information from DB.
total employees who were not deleted.
total employees who have security access and are not deleted.
total employees still active;
this is my Employee collection sample document
{
_id:'5ec25e74d028af28343f1061'
isDeleted:false
securityAccess:true
details:'60475b7a93ac45d64a5957b0'
}
this is EmployeeData collection document
{
_id:'60475b7a93ac45d64a5957b0'
emplyeeId:'5ec25e74d028af28343f1061'
isActive:'active',
salary:225543.00,
department:'sales'
}
I need to get this data from one query using some kind of aggregations but I'm not much familiar with the MongoDB queries.
the expected result looks like this.
Total Employees | Active Employees | Security Access
10 5 2
$match to check isDeleted condition
$lookup with EmployeeData
$group by null
get total employees count,
count total security access if securityAccess is true
count total active employees if isActive is 'active'
db.Employee.aggregate([
{ $match: { isDeleted: false } },
{
$lookup: {
from: "EmployeeData",
localField: "_id",
foreignField: "emplyeeId",
as: "activeEmployees"
}
},
{
$group: {
_id: null,
totalEmployees: { $sum: 1 },
securityAccess: {
$sum: {
$cond: ["$securityAccess", 1, 0]
}
},
activeEmployees: {
$sum: {
$cond: [
{ $eq: [{ $first: "$activeEmployees.isActive" }, "active"] },
1,
0
]
}
}
}
}
])
Playground
I'm trying to grasp the mongodb concepts by translating some of our sql queries into mongo aggregation framework.
I have an sql code:
select dbo.VisitNo(u.id) as visitNo , o.id, o.PatientId, u.VisitDate
from dbo.Observation o
join sbo.ProspectiveFollowUp u on u.rootid = o.Id
order by o.PatientId
The dbo.VisitNo is implemented as:
CREATE FUNCTION dbo.VisitNo(#Id int)
RETURNS INT
AS
BEGIN
DECLARE #VisitDate date, #RootId int
SELECT #VisitDate=VisitDate, #RootId=RootId FROM dbo.ProspectiveFollowUp WHERE Id=#Id
RETURN (SELECT COUNT(1) FROM dbo.ProspectiveFollowUp WHERE RootId = #RootId AND VisitDate <= #VisitDate)
END
result:
My document in Mongo has following structure:
{
"_id",
"values":[
{
"Id",
"PatientId",
"ProspectiveFollowUp":[
"Id",
"RootId",
"VisitDate"
]
}
]
}
The values array has always one element, but that's how the data was imported. ProspectiveFollowUp has at least one record.
Creating query for retrieving the data was rather easy:
db.dbo_ObservationJSON.aggregate([
{ $unwind: '$values' },
{
$project: {
_id: 0,
Id: '$values.Id',
PatientId: '$values.PatientId',
VisitDate: '$values.ProspectiveFollowUp.VisitDate'
}
},
{ $unwind: '$VisitDate' },
{ $sort: { PatientId: 1 } }
])
The harder part is the custom function itself. I can't think outside od tsql world yet, so I have hard time getting this to work. I have translated the function into mongo the following way:
var id = 4
var result = db.dbo.ObservationJSON.aggregate([
{ $unwind: '$values' },
{ $unwind: '$values.ProspectiveFollowUp' },
{ $project: { Id: '$values.ProspectiveFollowUp.Id', RootId: '$values.ProspectiveFollowUp.RootId', VisitDate: '$values.ProspectiveFollowUp.VisitDate', _id:0 }},
{ $match: { Id: id }}
]).toArray()[0]
var totalResult = db.dbo_ObservationJSON.aggregate([{
$unwind: {
path: '$values'
}
}, {
$unwind: {
path: '$values.ProspectiveFollowUp'
}
}, {
$project: {
Id: '$values.ProspectiveFollowUp.Id',
RootId: '$values.ProspectiveFollowUp.RootId',
VisitDate: '$values.ProspectiveFollowUp.VisitDate'
}
}, {
$match: {
RootId: result.RootId,
VisitDate: {
$lte: result.VisitDate
}
}
},{$count: 'total'}]).toArray()[0]
But don't know how to integrate it into the aggregation function above.
Can I write the entire sql query equivalent into one mongo aggregate expression?
I finally got it to work.
db.dbo_ObservationJSON.aggregate([
{ $unwind: '$values' },
{ $unwind: { path: '$values.ProspectiveFollowUp', "includeArrayIndex": "index" } },
{
$project: {
_id: 0,
VisitNo: { $add: ['$index', 1] },
RootId: '$values.ProspectiveFollowUp.RootId',
PatientId: '$values.PatientId',
VisitDate: '$values.ProspectiveFollowUp.VisitDate'
}
},
{
$sort: {
PatientId: 1
}
}
]);
Hi I want to change my sql query to mongo aggregation.
select c.year, c.minor_category, count(c.minor_category) from Crime as c
group by c.year, c.minor_category having c.minor_category = (
Select cc.minor_category from Crime as cc where cc.year=c.year group by
cc.minor_category order by count(*) desc, cc.minor_category limit 1)
I tried do something like this:
db.crimes.aggregate({
$group: {
"_id": {
year: "$year",
minor_category :"$minor_category",
count: {$sum: "$minor_category"}
}
},
},
{
$match : {
minor_category: ?
}
})
But i stuck in $match which is equivalent to having, but i dont know how to make subqueries in mongo like in my sql query.
Can anybody can help me ?
Ok based on the confirmation above , the below query should work.
db.crime.aggregate
([
{"$group":{"_id":{"year":"$year","minor":"$minor"},"count":{"$sum":1}}},
{"$project":{"year":"$_id.year","count":"$count","minor":"$_id.minor","document":"$$ROOT"}},
{"$sort":{"year":1,"count":-1}},
{"$group":{"_id":{"year":"$year"},"orig":{"$first":"$document"}}},
{"$project":{"_id":0,"year":"$orig._id.year","minor":"$orig._id.minor","count":"$orig.count"}}
)]
This translates into the following MongoDB query:
db.crime.aggregate({
$group: { // group by year and minor_catetory
_id: {
"year": "$year",
"minor_category": "$minor_category"
},
"count": { $sum: 1 }, // count all documents per group,
}
}, {
$sort: {
"count": -1, // sort descending by count
"minor_category": 1 // and ascending by minor_category
}
}, {
$group: { // now we get the highst element per year
_id: "$_id.year", // so group by year
"minor_category": { $first: "$_id.minor_category" }, // and get the first (we've sorted the data) value
"count": { $first: "$count" } // same here
}
}, {
$project: { // remove the _id field and add the others in the right order (if needed)
"_id": 0,
"year": "$_id",
"minor_category": "$minor_category",
"count": "$count"
}
})
How I can implement on MongoDb this SQL Query
SELECT TOP 100 * FROM Tracks
WHERE ID IN (SELECT MAX(ID) FROM Tracks WHERE UserID IN ([UserIDs...]) GROUP BY UserID)
Tracks structure:
Tracks[{_id, userId, {lat, lon}, dateCreate, ...}, ...]
Thanks!
You'd want to use the aggregation framework for this:
db.Tracks.aggregate( [
{ $match: { 'UserID': { $in: [ UserIDs ] } } },
{ $group: { _id: '$UserID', max: { $max: '$_id' } },
{ $sort: { $max: -1 } },
{ $limit: 100 }
] );
First we match against the wanted UserIDs, then we group depending on UserID and also put the maximum _id value in the new max field. Then we sort by max descendently to get the highest max numbers first and then we limit by the top 100.