MongoDB aggregate query $match - mongodb

I create a query that returns the farmland details and all events that is connected with it (see below)
Now I want to filter and return only events that have the status field not equal to delete. I tried with $match operator but it doesn't work... Is there someone who can help me with?
Here are the collections of the database:
Farmland collections
{
"_id" : ObjectId("5909d9bc19383e2a16378271"),
"SUID" : "IT0001",
"id" : "A",
"UUID" : "CAL123",
"name" : "Pratosaiano (Maza)",
"status" : "close"
}
Events collections
...
{
"_id" : ObjectId("5909e3387786e52c90f158da"),
"SUID" : "IT0001",
"farmland" : "B",
"opening" : "00:00",
"closing" : "00:00",
"type" : "scheduled",
"days" : [
0,
0,
0,
0,
0,
0,
0
],
"active" : true,
"status" : "add",
"id" : 204
},
{
"_id" : ObjectId("590b4ec6cdddea05130fbc3b"),
"SUID" : "IT0001",
"farmland" : "B",
"opening" : "00:00",
"closing" : "01:00",
"type" : "semiautomatic",
"active" : true,
"status" : "add",
"id" : 16
}
...
The query:
db.farmlands.aggregate([
{
$match: {
"SUID": "IT0001",
"id": "B",
}
},
{
$lookup: {
localField: "id",
from: "events",
foreignField: "farmland",
as: "events"
}
},
{
$project: {
"_id": 0,
"SUID": 1,
"id": 1,
"name": 1,
"events.id": 1,
"events.type": 1,
"events.opening": 1,
"events.closing": 1,
"events.days": 1,
"events.active": 1,
"events.status": 1
}
}]);
The output of this query
{
"_id" : ObjectId("5909d9bc19383e2a16378272"),
"SUID" : "IT0001",
"id" : "B",
"UUID" : "CAL123",
"name" : "Pratosaiano (Maza)",
"status" : "close",
"events" : [
{
"_id" : ObjectId("5909da8312452a289bbb62c1"),
"SUID" : "IT0001",
"farmland" : "B",
"opening" : "07:00",
"closing" : "08:00",
"type" : "scheduled",
"days" : [
0,
0,
0,
0,
0,
0,
0
],
"active" : true,
"status" : "update",
"id" : 237
}, ...
]
}

Related

Mongo db query for multiple conditions

I have a Mongodb Json which look like this
{
"_id" : "5b862ebecebe455a1744",
"userId" : "111",
"courses" : [
{
"stateName" : "statge 1",
"courseId" : "1453",
"courseName" : "Program Training 1",
"duration" : 1,
"lag" : 0,
"courseType" : "1",
"transitionType" : "onComplete",
"scheduledStartDate" : ISODate("2018-07-27T16:23:14.000+05:30"),
"scheduledEndDate" : ISODate("2018-07-27T16:23:14.000+05:30"),
"courseProgress" : 0,
"ASD" : ISODate("2018-09-17T23:18:30.636+05:30"),
"score" : 0
},
{
"stateName" : "stage 2",
"courseId" : "1454",
"courseName" : "Program Assessment 1",
"duration" : 1,
"lag" : 0,
"courseType" : "2",
"transitionType" : "onComplete",
"scheduledStartDate" : ISODate("2018-07-28T16:23:14.000+05:30"),
"scheduledEndDate" : ISODate("2018-07-28T16:23:14.000+05:30"),
"courseProgress" : 0,
"score" : 0
},
{
"stateName" : "stage 3",
"courseId" : "911",
"courseName" : "Program Training 3",
"duration" : 1,
"lag" : 0,
"courseType" : "1",
"transitionType" : "onComplete",
"scheduledStartDate" : ISODate("2018-07-29T16:23:14.000+05:30"),
"scheduledEndDate" : ISODate("2018-07-29T16:23:14.000+05:30"),
"courseProgress" : 0,
"score" : 0
}
],
"userStatus" : 1,
"modified" : ISODate("2018-09-12T11:49:47.400+05:30"),
"created" : ISODate("2018-09-12T11:49:47.400+05:30"),
"completionStatus" : "IP",
"currentState" : {
"courseProgress" : 0,
"stateName" : "statge 1",
"courseId" : "1453",
"courseName" : "Program Training 1"
}
}
I want to find a query where condition is. Please help, as I am new to mongodb
courses.transitionType = oncomplete
(PROGRESS<100||(PROGRESS==100&&ASD exists false))
And print Result something like this which contain these below data
{
"_id" : "5b862ebecebe455a1744",
"courseData" : {
"userId" : "4688",
"courseId" : "1476",
"courseProgress" : 0
}
}
You will have to use an aggregation with a $match stage and a $project to format your result.
The tricky part of your request is that you want an answer by course, but 1 item of your collection contains many courses. So first, you can use the $unwind stage to separate every course
db.[CollectionName].aggregate([
{
$unwind : '$courses'
}
{
$match: {
'courses.transitionType': 'onComplete',
$or: [
{
'courses.courseProgress': { $lt: 100 }
},
{
'courses.courseProgress': 100,
ASD: { $exists: 0 }
}
]
}
},
{
$project: {
_id: '0',
courseData: {
userId: '$courses.userId',
courseId: '$courses.courseId',
courseProgress: '$courses.courseProgress'
}
}

Fetch data from mongodb in three different field according to condition

i have a User collection having structure as below
{
"_id" : ObjectId("596845524e20b8328d61b01f"),
"created_at" : ISODate("2017-07-10T04:15:14.327Z"),
"status" : 1,
"updated_at" : ISODate("2017-08-22T07:29:44.000Z"),
"is_activated" : 0,
"totalrating" : 0,
"is_admin" : 0,
"basic_detail" : {
"first_name" : "c",
"last_name" : "f",
"password" : "$2a$10$.WG",
"user_type" : 1,
"full_name" : "c f"
}
},
{
"_id" : ObjectId("596845524e20b8328d61b01d"),
"created_at" : ISODate("2017-07-10T04:15:14.327Z"),
"status" : 1,
"updated_at" : ISODate("2017-08-22T07:29:44.000Z"),
"is_activated" : 0,
"totalrating" : 0,
"is_admin" : 0,
"basic_detail" : {
"first_name" : "c",
"last_name" : "f",
"user_type" : 2,
"full_name" : "c f"
}
},
{
"_id" : ObjectId("596845524e20b8328d61b01g"),
"created_at" : ISODate("2017-07-10T04:15:14.327Z"),
"status" : 1,
"updated_at" : ISODate("2017-08-22T07:29:44.000Z"),
"is_activated" : 0,
"totalrating" : 0,
"is_admin" : 0,
"basic_detail" : {
"first_name" : "c",
"last_name" : "f",
"user_type" : 3,
"full_name" : "c f"
}
}
i want to fetch data through aggreagte query and want data like below
{
"totaluser":3,
"totalho":1,//all those record having user_type=1,
"totaltr":2,//all those record having user_type=2,
"totalcf":3,//all those record having user_type=3
}
trying to do same with the help of group but not able to do please help I am using mongodb 3.4
[{ $facet:
{
totaluser: [ { $count: "totaluser" } ],
totalho: [ {$match:{"basic_detail.user_type":1}},{ $count: "totalho" }],
//other fields
}
},
{
$addFields:{
"totaluser": {
$let:{
vars:{totaluserObj:{ $arrayElemAt: [ "$totaluser", 0 ] }},
in:"$$totaluserObj.totaluser"
}
},
"totalho": {
$let:{
vars:{totalhoObj:{ $arrayElemAt: [ "$totalho", 0 ] }},
in:"$$totalhoObj.totalho"
}
}
}
}]

Use $match on more than 1 field with aggregate and $lookup

I have the following mongo query.
db.ServiceProvider.aggregate([
{
$unwind: "$PostCommentUserIDs"
},
{
$lookup:
{
from: "Parents",
localField: "PostCommentUserIDs",
foreignField: "ID",
as: "ParentDetailsArr"
}
},
{
$match: { "ParentDetailsArr": { $ne: [] } }
}
])
It gives following result:
{
"_id" : ObjectId("57245af1588aec5b118b4567"),
"ServiceProviderID" : 3,
"Title" : "test",
"PostedMessage" : "test",
"TotalComments" : 0,
"TotalShares" : 0,
"TotalThanks" : 0,
"AddedOn" : "2016-04-30",
"LastModifiedOn" : "2016-04-30 07:12:49",
"PostAttachment" : {
"ImagePath" : ""
},
"PostCommentUserIDs" : "3",
"PostComments" : [
{
"ID" : "1462000372388480634",
"UserID" : 3,
"CommentMessage" : "1",
"TotalThanks" : 0,
"AddedOn" : "2016-04-30 07:12:52",
"LastModifiedOn" : "2016-04-30 07:12:52",
"CommentAttachment" : {
"ImagePath" : ""
}
},
],
"Subscriber" : [ ],
"ParentDetailsArr" : [
{
"_id" : ObjectId("572447e6588aec32108b4569"),
"ID" : "3",
"UID" : "0Xb1fHqzR3HZVJWQc8aAbB77UkwSnmasdQrtp9qySVdqipsYs6eC7rEt",
"Name" : "Chinmay Kulkarni",
"ProfileImagePath" : "images3_3_1460348144#SIZE#.jpeg"
}
]
}
{
"_id" : ObjectId("57246137588aec41118b4567"),
"ServiceProviderID" : 3,
"Title" : "test",
"PostedMessage" : "test",
"TotalComments" : 0,
"TotalShares" : 0,
"TotalThanks" : 0,
"AddedOn" : "2016-04-30",
"LastModifiedOn" : "2016-04-30 07:39:35",
"PostAttachment" : {
"ImagePath" : ""
},
"PostCommentUserIDs" : "3",
"PostComments" : [
{
"ID" : "14620019791507102321",
"UserID" : 3,
"CommentMessage" : "1",
"TotalThanks" : 0,
"AddedOn" : "2016-04-30 07:39:39",
"LastModifiedOn" : "2016-04-30 07:39:39",
"CommentAttachment" : {
"ImagePath" : ""
}
},
],
"Subscriber" : [ ],
"ParentDetailsArr" : [
{
"_id" : ObjectId("572447e6588aec32108b4569"),
"ID" : "3",
"UID" : "0Xb1fHqzR3HZVJWQc8aAbB77UkwSnmasdQrtp9qySVdqipsYs6eC7rEt",
"Name" : "Chinmay Kulkarni",
"ProfileImagePath" : "images3_3_1460348144#SIZE#.jpeg"
}
]
}
I want to modify the above query and add the _id condition to it. So that it only gives me 1 result with matches with given _id.
But not able to crack it through. Please help!
The $match takes filter criterion. Add the _id query filter criteria inside $match aggregate function - https://docs.mongodb.org/manual/reference/operator/aggregation/match/
Run the query with below $match condition at last pipeline of your aggregate query.
db.ServiceProvider.aggregate([
{
$unwind: "$PostCommentUserIDs"
},
{
$lookup:
{
from: "Parents",
localField: "PostCommentUserIDs",
foreignField: "ID",
as: "ParentDetailsArr"
}
},
{
$match: { "ParentDetailsArr": { $ne: [] }, "_id" : ObjectId("XXXX") }
}
])

Using mongodb, how can I return a unique list with one field in common?

I 'm trying to return a list of unique titles by the same user/author. I used
posts.find(
{'student':user , 'class_number':0}
).sort('created', -1).limit(num).toArray(function(err, items) {
which works well as long as there is a 'class_number':0 which there may not always be. So I tried using distinct but I'm not sure how I can provide a query for unique titles. Is there a better way to do this? Here's some data:
posts.distinct(
{'student':user , 'title':?}
)
.sort('created', -1).limit(num).toArray(function(err, items) {
Data:
{
"_id" : ObjectId("53aa0093e99034914b000003"),
"ans" : 1,
"author" : "niko",
"class_number" : 1,
"comments" : [ ],
"copy" : false,
"created" : 1403650195222,
"current" : "",
"memorized" : 1,
"permalink" : "newtest_106677414836872",
"rem" : 257,
"student" : "niko",
"tags" : [ ],
"title" : "newtest"
}
{
"_id" : ObjectId("53aa0093e99034914b000004"),
"ans" : 1,
"author" : "niko",
"class_number" : 2,
"comments" : [ ],
"copy" : false,
"created" : 1403650195253,
"current" : "",
"memorized" : 1,
"permalink" : "newtest_91237262691445",
"rem" : 603,
"student" : "niko",
"tags" : [ ],
"title" : "newtest"
}
{
"_id" : ObjectId("53aa0093e99034914b000002"),
"ans" : 2,
"author" : "niko",
"class_number" : 0,
"comments" : [ ],
"copy" : false,
"created" : 1403650195217,
"current" : "",
"memorized" : 1,
"permalink" : "newtest_5614600780868",
"rem" : 391,
"student" : "niko",
"tags" : [ ],
"title" : "newtest"
}
{
"title" : "rockin",
"author" : "niko",
"student" : "niko",
"current" : "",
"permalink" : "rockin_44917561926464",
"tags" : [ ],
"comments" : [ ],
"created" : 1403673810202,
"memorized" : 1,
"ans" : 1,
"rem" : 1,
"copy" : false,
"class_number" : 0,
"_id" : ObjectId("53aa5cd2ff9163968f000002")
}
{
"title" : "rockin",
"author" : "niko",
"student" : "niko",
"current" : "",
"permalink" : "rockin_68780016699996",
"tags" : [ ],
"comments" : [ ],
"created" : 1403673810204,
"memorized" : 1,
"ans" : 1,
"rem" : 1,
"copy" : false,
"class_number" : 1,
"_id" : ObjectId("53aa5cd2ff9163968f000003")
}
If you are looking for matching the "student" to the "author" then your best bet for hitting this all in one go is the aggregation framework:
db.collection.aggregate([
{ "$group": {
"_id": {
"user": {
"$cond": [
{ "$eq": [ "$student", "$author" ] },
"$student",
false
]
},
"title": "$title"
}
}},
{ "$match": { "_id.user": { "$ne": false } }}
])
So the $group brings all the "distinct" combinations of "user" and "title" together while conditionally evaluating under the $cond operator whether those fields are matching or not.
The $match just filters out those distinct "titles" where the user match evaluated to false.

Aggregate inside document in mongodb

I have document sales
db.sale.findOne({_id : ObjectId("52ea4dd29dbc7923107ddb97")})
{
"_id" : ObjectId("52ea4dd29dbc7923107ddb97"),
"firm" : ObjectId("52e56c009dbc794999ea5c3d"),
"patient" : {
"last" : "",
"first" : ""
},
"doc" : "",
"hospital" : "",
"discount" : 0,
"dd" : "",
"mode" : "cash",
"invoice" : "300114-undefined-1",
"items" : [
{
"bat" : "BJFE",
"narco" : 0,
"name" : "GDRNCCD",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 1,
"exp" : "1425168000000"
},
{
"bat" : "",
"narco" : 0,
"name" : "GDRN vbhjdsfb",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 0,
"exp" : "[object Object]"
},
{
"bat" : "",
"narco" : 0,
"name" : "GDRN vbhjdsfb",
"mrp" : 1,
"free" : 0,
"qty" : 1,
"item_discount" : 0,
"wpr" : 0,
"exp" : "[object Object]"
}
],
"date" : ISODate("2014-01-30T00:00:00Z"),
"mob" : "",
"email" : ""
}
How can I Aggregate total numbers if items in one field and sum up mrp *qty of all the items into one field.
I have read the mognodb aggregation but it only aggregates among group of matched documents not inside a single document. Is it possile?
{
"_id" : ObjectId("52ea4dd29dbc7923107ddb97"),
"firm" : ObjectId("52e56c009dbc794999ea5c3d"),
'total_items' : items.length,
"total" : mrp*qty of all items,
}
db.sales.aggregate(
{$unwind: "$items"},
{$project: {_id: 1,firm:1, total: {$multiply: ["$items.mrp", "$items.qty"]}}},
{$group: {_id: {"id":"$_id", firm:"$firm"}, count: {$sum:1} , total : {$sum:"$total"}}}
)
With a slight change : _id contains id and firm, you will need an extra projection to match your desired document, but I don't think it's important.
Plus, you can easily change to group by farm only
Thanks to Orid,I tried this,
db.sale.aggregate(
{ $match :{ firm :ObjectId("52e56c009dbc794999ea5c3d") } },
{$project : {day : {$dayOfMonth : '$date'},items :1,patient :1,invoice :1}},
{$match : {day: {$gte : new Date().getDate()}}},
{$unwind : "$items"},
{$project: {_id: 1,patient:1,invoice :1, total: {$multiply: ["$items.mrp", "$items.qty"]}}},
{$group: {_id: {"id":"$_id", invoice:"$invoice",patient :"$patient"}, count: {$sum:1} , total : {$sum:"$total"}}})
Result
{
"result" : [
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbaf"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 2,
"total" : 25
},
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbb0"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 1,
"total" : 1
},
{
"_id" : {
"id" : ObjectId("52eab6129dbc7923107ddbae"),
"invoice" : "310114-undefined-1",
"patient" : {
"last" : "",
"first" : ""
}
},
"count" : 2,
"total" : 5
}
],
"ok" : 1
}