MongoDB Query Aggregation - mongodb

I need a query that takes multiple 'companyID's' and return the count for each company.
Currently this query only does this for one companyID and it does not return the id but just 'null' like show below.
I understand that I can use the 'in' operator for multiple companyID's but not sure how I would go about having the query return the count for multiple companyID's
db.getCollection('reg').aggregate([ {
'$match' : {
'$and' : [
{
'companyID' : 11
},
{
'created' : {
'$gte' : 1556726597
}
},
{
'created' : {
$lt : 1580572997
}
}
]
}
},
{
'$project' : {
'testID' : 1,
}
},
{
'$group' : {
'_id' : '$testID',
'registrationsCount' : {'$sum' : 1},
},
},
{
$group: {
_id: null,
count: { $sum: 1 }
}
}
])
The result below
{
"_id" : null,
"count" : 10.0
}
Schema below
{
"_id" : NumberLong(1),
"appUserID" : NumberLong(4294967295),
"companyID" : NumberLong(5),
"created" : NumberLong(1372625588),
"testID" : NumberLong(11),
"isCheckIn" : true,
"lastModified" : NumberLong(1372625588),
"source" : "upload",
"timeArrived" : NumberLong(1343062512),
}

I think you need to do 2 things
first
'$match' : {
'$or': [
'$and' : [
{
'companyID' : 11
},
{
'created' : {
'$gte' : 1556726597
}
},
{
'created' : {
$lt : 1580572997
}
}
]
// ... add the other ids you need
]
}
And second
{
'$group' : {
'_id' : '$testID',
'registrationsCount' : {'$sum' : 1},
},
},
{
$group: {
_id: '$testID', // or '$_id' not sure
count: { $sum: 1 }
}
}
Hope this helps!

Related

MongoDb Group BY MAX date and get field from this document

Look my problen hehe. I don't know how I can do it.
There are a lot of assetState 1..n I would like do aggregation for get last asset state group by asset.
Mongo collection : assetState
[
{
"lsd" : {
"$id" : ObjectId("lucas")
},
"stateDate" : ISODate("2018-09-10T16:26:44.501Z"),
"assetId" : ObjectId("5b96b7645f2b3c0101520s60")
},
{
"lsd" : {
"$id" : ObjectId("denner")
},
"stateDate" : ISODate("2018-09-10T17:26:44.501Z"),
"assetId" : ObjectId("5b96b7645f2b3c0101520s60")
},
{
"lsd" : {
"$id" : ObjectId("denner")
},
"stateDate" : ISODate("2018-09-10T18:26:44.501Z"),
"assetId" : ObjectId("5b96b7645f2a8c0001530f61")
},
{
"lsd" : {
"$id" : ObjectId("lermen")
}
},
"stateDate" : ISODate("2018-09-10T20:26:44.501Z"),
"assetId" : ObjectId("5b96b7645f2a8c0001530f61")
},
{
"lsd" : {
"$id" : ObjectId("floripa")
},
"stateDate" : ISODate("2018-09-10T19:26:44.501Z"),
"assetId" : ObjectId("5b96b7645f2a8c0001530f61")
}
]
I would like get max "stateDate", so I need get LSD from same row(document).
Expected result:
{
"lsd" : {
"$id" : ObjectId("lermen")
},
"stateDate" : ISODate("2018-09-10T20:26:44.501Z")
}
I tried to do:
db.getCollection('assetState').aggregate([
{
$group: {
"_id": {"assetId": "$assetId"},
"stateDate": {
"$max": "$stateDate"
},
"lsd": {$last: "$lsd"} // I tried change $max to $min and $last it din't work :(
}
]);
Result:
{
"lsd" : {
"$id" : ObjectId("floripa")
},
"stateDate" : ISODate("2018-09-10T20:26:44.501Z")
}
Many Thanks
Try this query
db.getCollection('assetState').aggregate([
{$sort:{"stateDate":-1}},
]).limit(1)
you can $sort descending before $group and gets the first item of each group with $arrayElemAt
db.getCollection('assetState').aggregate([
{ $sort: { stateDate: -1 } },
{ $group: { _id: { "assetId" : "$assetId" },
states: { $push: "$$ROOT" }
}
},
{ $project: { "last_asset": { $arrayElemAt: [ "$states", 0 ] }, _id:0 } },
])
Result:
/* 1 */
{
"last_asset" : {
"_id" : ObjectId("5db2b34fa1b70230bba9c4d9"),
"lsd" : "denner",
"stateDate" : ISODate("2018-09-10T17:26:44.501Z"),
"assetId" : "5b96b7645f2b3c0101520s60"
}
}
/* 2 */
{
"last_asset" : {
"_id" : ObjectId("5db2b34fa1b70230bba9c4db"),
"lsd" : "lermen",
"stateDate" : ISODate("2018-09-10T20:26:44.501Z"),
"assetId" : "5b96b7645f2a8c0001530f61"
}
}
You could use $unwind (aggregation)
https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/
I have this for the group by phase:
{
_id: {"sourceOfEvent":"$sourceOfEvent","vehicleId":"$vehicleId"},
maxTimeOfEvent: { $max: "$timeOfEvent" }
}
So group by on 2 fields and I use the max to get the max of the timeOfEvent (which is a date)

mongodb help required for one business problem

Business Problem:
We are seeing a single customerOrderNumber with all versions having “INACTIVE.” This is a problem for multiple reasons. My goal is to be able to pull a list of customerOrderNumbers with ONLY INACTIVE statuses.
Database and Query: XXX_ORDERMGMT_1
db.getCollection('customerOrder').aggregate( [ { $match: { 'orderDocument.accountInfo.ban': '123456' } }, { $group: { _id: { customerOrderNumber : '$orderReference.customerOrderNumber', status : '$orderReference.customerOrderStatus' }, count: { $sum: 1 } }, }] )
OUTPUT:
/* 1 / { "_id" : { "customerOrderNumber" : "123", "status" : "COMPLETED" }, "count" : 1.0 } / 2 */ { "_id" : { "customerOrderNumber" : "123", "status" : "INACTIVE" }, "count" : 2.0 }
DESIRED_OUTPUT:
/* 1 */ { "_id" : { "customerOrderNumber" : "123", "statusGroupings" : { "status" : "COMPLETED", "status_cnt" : 1.0 }, { "status" : "INACTIVE", "status_cnt" : 2.0 } }, "count" : 3.0 }
( My approach was to pull all customerOrders by status and count, parse it into a relational format, and filter by only customerOrderNumbers with all versions being INACTIVE. This may not be the best way and I’m open to thoughts.)
The following query can get us the expected output:
db.getCollection("customerOrder").aggregate([
{
$match:{
"orderDocument.accountInfo.ban":"123456"
}
},
{
$group:{
"_id":{
"customerOrderNumber":"$orderReference.customerOrderNumber",
"status":"$orderReference.customerOrderStatus"
},
"customerOrderNumber":{
$first:"$orderReference.customerOrderNumber"
},
"status":{
$first:"$orderReference.customerOrderStatus"
},
"count":{
$sum:1
}
}
},
{
$group:{
"_id":"$customerOrderNumber",
"customerOrderNumber":{
$first:"$customerOrderNumber"
},
"statusGroupings":{
$push:{
"status":"$status",
"status_cnt":"$count"
}
},
"count":{
$sum:"$count"
}
}
},
{
$project:{
"_id":0
}
}
]).pretty()
Data set:
{
"_id" : ObjectId("5d9bf7204ed5d873f39a773b"),
"orderDocument" : {
"accountInfo" : {
"ban" : "123456"
}
},
"orderReference" : {
"customerOrderNumber" : 1,
"customerOrderStatus" : "INACTIVE"
}
}
{
"_id" : ObjectId("5d9bf7204ed5d873f39a773c"),
"orderDocument" : {
"accountInfo" : {
"ban" : "123456"
}
},
"orderReference" : {
"customerOrderNumber" : 1,
"customerOrderStatus" : "COMPLETED"
}
}
{
"_id" : ObjectId("5d9bf7204ed5d873f39a773d"),
"orderDocument" : {
"accountInfo" : {
"ban" : "123456"
}
},
"orderReference" : {
"customerOrderNumber" : 1,
"customerOrderStatus" : "INACTIVE"
}
}
{
"_id" : ObjectId("5d9bf7204ed5d873f39a773e"),
"orderDocument" : {
"accountInfo" : {
"ban" : "123456"
}
},
"orderReference" : {
"customerOrderNumber" : 1,
"customerOrderStatus" : "INACTIVE"
}
}
Output:
{
"customerOrderNumber" : 1,
"statusGroupings" : [
{
"status" : "COMPLETED",
"status_cnt" : 1
},
{
"status" : "INACTIVE",
"status_cnt" : 3
}
],
"count" : 4
}

How to write mongo query

How I can get the total number of seats available for a particular movie (seats present in all the theatres for that movie) from the mongodb schema below.
I need to write a mongo query to get the results
{
"_id" : ObjectId("5d637b5ce27c7d60e5c42ae7"),
"name" : "Bangalore",
"movies" : [
{
"name" : "KGF",
"theatres" : [
{
"name" : "PVR",
"seats" : 45
},
{
"name" : "IMAX",
"seats" : 46
}
]
},
{
"name" : "Avengers",
"theatres" : [
{
"name" : "IMAX",
"seats" : 50
}
]
}
],
"_class" : "com.BMS_mongo.ZZ_BMS_mongo_demo.Entity.CityInfo"
}
I have written this code :
db.cities.aggregate( [
{ "$unwind" : "$movies" }, { "$unwind" : "$theatres" } ,
{ "$group" : { _id : "$movies.theatre`enter code here`s.seats" ,
total : { "$sum" : "$seats" } }
}
] )
My schema:
The following query can get us the expected output:
db.collection.aggregate([
{
$unwind:"$movies"
},
{
$unwind:"$movies.theatres"
},
{
$group:{
"_id":"$movies.name",
"movie":{
$first:"$movies.name"
},
"totalSeats":{
$sum:"$movies.theatres.seats"
}
}
},
{
$project:{
"_id":0
}
}
]).pretty()
Data set:
{
"_id" : ObjectId("5d637b5ce27c7d60e5c42ae7"),
"name" : "Bangalore",
"movies" : [
{
"name" : "KGF",
"theatres" : [
{
"name" : "PVR",
"seats" : 45
},
{
"name" : "IMAX",
"seats" : 46
}
]
},
{
"name" : "Avengers",
"theatres" : [
{
"name" : "IMAX",
"seats" : 50
}
]
}
],
"_class" : "com.BMS_mongo.ZZ_BMS_mongo_demo.Entity.CityInfo"
}
Output:
{ "movie" : "Avengers", "totalSeats" : 50 }
{ "movie" : "KGF", "totalSeats" : 91 }
Query:
db.movie.aggregate([{ $unwind: { path: "$movies",} },
{ $unwind: { path: "$movies.theatres",} },
{ $group: { _id: "$movies.name", "moviename": { $first: "$movies.name" },
"totalSeats": { $sum: "$movies.theatres.seats" }} }])
I got the answer using this query ...
db.cities.aggregate( [
{ "$match" : { "name" : "Bangalore" } },
{ "$unwind" : "$movies" } ,
{ "$match" : {"movies.name" : "KGF"} },
{ "$unwind" : "$theatres" },
{ "$group" : { _id : "$movies.name", total : { "$sum" : "$movies.theatres.seats"
} } }
] )

How to take the duplicate records in mongodb

Here i have two document ,in this documents childNodes array ID is duplicate means , i want to take the userID and pedagogyID of the record,as per my documents second document under childNodes array 798 is coming duplicate, so i want to take the records
Documents
{
"userID" : "A",
"pedagogyID" : "100",
"summary" : {
"LearnProgress" : {
"childNodes" : [
{
"ID" : "123",
"status" : "in-progress"
},
{
"ID" : "456",
"status" : null
},
{
"ID" : "333",
"status" : null
}
],
}
}
}
{
"userID" : "B",
"pedagogyID" : "200",
"summary" : {
"LearnProgress" : {
"childNodes" : [
{
"ID" : "789",
"status" : "in-progress"
},
{
"ID" : "1010",
"status" : null
},
{
"ID" : "789",
"status" : null
}
],
}
}
}
Expected Output
{
"userID" : "B",
"pedagogyID" : "200",
}
MY Code
db.collectionname.aggregate(
[
{"$unwind":"$summary.LearnProgress.childNodes"},
{"$group":{
"_id":{"_id":"$_id","ID":"$summary.LearnProgress.childNodes.ID"},
"userID":{"$first":"$userID"},
"pedagogyID":{"$first":"$pedagogyID"},
"count":{"$sum":1}
}},
{"$match":{"count":{"$gt":1}}},
{"$group":{"_id":{"userID":"$userID","pedagogyID":"$pedagogyID"}}},
{"$replaceRoot":{"newRoot":"$_id"}}
],
{ allowDiskUse:true }
)
You can use below aggregation.
db.colname.aggregate([
{"$unwind":"$summary.LearnProgress.childNodes"},
{"$group":{
"_id":{"_id":"$_id","ID":"$summary.LearnProgress.childNodes.ID"},
"userID":{"$first":"$userID"},
"pedagogyID":{"$first":"$pedagogyID"},
"count":{"$sum":1}
}},
{"$match":{"count":{"$gt":1}}},
{"$group":{"_id":{"userID":"$userID","pedagogyID":"$pedagogyID"}}},
{"$replaceRoot":{"newRoot":"$_id"}}
],{"allowDiskUse":true})
db.collectionname.aggregate(
// Pipeline
[
// Stage 1
{
$unwind: {
path : "$summary.LearnProgress.childNodes",
}
},
// Stage 2
{
$group: {
_id:'$summary.LearnProgress.childNodes.ID',
count:{$sum:1},
pedagogyID:{$first:'$pedagogyID'},
userID:{$first:'$userID'}
}
},
// Stage 3
{
$match: {
count:{$gt:1}
}
},
// Stage 4
{
$project: {
userID:1,
pedagogyID:1,
_id:0
}
},
]
);

Some extra tags while doing update based on a result set

Basically, I want to upate .nid with .id when coll2 has coll1.id in its abclist
db.<coll1>.find().forEach( function(elem) {
db.<coll1>.update (
{_id : elem._id },
{ "$set" : {
nid : db.<coll2>.aggregate ( [
{"$unwind" : "$abclist" } ,
{"$match" : { "abclist" : elem._id } },
{"$project" : { _id :1 } } ]
)
}}
)
})
When I do the below part separately
db.<coll2>.aggregate ([
{ "$unwind" : "$abclist" } ,
{ "$match" : { "abclist" : elem._id } },
{"$project" : { _id :1 } }
])
I get the nice response with just the object id.
But when done in the above update statement, by nid gets updated as below with extra firstBatch/_cursor etc etc
"nid" : { "_firstBatch" : [ { "_id" : ObjectId("539ebded1c70fac84cd17510") } ], "_cursor" : { } } }
Any idea how to avoid.
Thanks
Sathya