conditional aggregate query in golang - mongodb

i am using golang and mongodb.
my attendance collection looks like this -
{
"_id" : ObjectId("5708156b51230e8edcb01fd1"),
"college_id" : "tisl",
"stream" : "CS",
"semester" : "sem3",
"section" : "A",
"subject" : "PH301",
"date" : ISODate("2016-04-08T20:32:42.547Z"),
"teacher" : "Chandra Kanta Bhattacharya",
"atndnc" : [
{
"rollno" : "13000112115",
"name" : "Md Hossain Ahamed",
"attend" : true
},
{
"rollno" : "13000112116",
"name" : "Md Sajid Tagala",
"attend" : true
},
{
"rollno" : "13000112117",
"name" : "Nabarun Roy",
"attend" : false
},
{
"rollno" : "13000112118",
"name" : "Nikunj Mundra",
"attend" : true
}
]
}
I want to get report for each student in percentage as an array of object like:
[{"rollno" : "13000112115",
"name" : "Md Hossain Ahamed",
"prcntg" : 80},
{
"rollno" : "13000112116",
"name" : "Md Sajid Tagala",
"prcntg" : 60
},
{
"rollno" : "13000112117",
"name" : "Nabarun Roy",
"prcntg" : 90
},
{
"rollno" : "13000112118",
"name" : "Nikunj Mundra",
"prcntg" : 65
}]
and my conditions will be the following
college_id,stream,semester,section,subject,startingdate and enddate

bson.M{"$group":bson.M{"_id":{"rollno":bson.M{"$atndnc.rollno"}}}} in this line i am getting that error
This is due to the incorrect bson.M usage. You don't need to create a bson map if its a string (single value). So you could update that to:
bson.M{"$group":
bson.M{"_id": bson.M{"rollno":"$atndnc.rollno"}}
}
The equivalent of your aggregation pipeline in Go is below :
pipeline := []bson.M{
bson.M{"$match":
bson.M{"stream": "CS", "semester":"sem3", "section":"A"}},
bson.M{"$unwind": "$atndnc"},
bson.M{"$group":
bson.M{ "_id": bson.M{"rollno":"$atndnc.rollno", "name":"$atndnc.name"},
"count":bson.M{"$sum":1},
},
},
bson.M{"$project":
bson.M{"_id":"$_id.rollno", "name":"$_id.name", "count":"$count"}},
}
I would recommend to checkout MongoDB mgo driver page for examples and references.

Related

Update query on in the collection by "_id"

{
"_id" : "tenant/data/EMAIL/ENGLISH",
"tenantId" : "tenant2",
"channelType" : "EMAIL",
"template" : [
{
"_id" : "1",
"templateName" : "abc",
"effectiveStartDate" : ISODate("2017-01-01T12:00:00.000Z"),
"modifiedDate" : ISODate("2017-06-02T22:08:55.782Z"),
"active" : false
}
]
}
I need to update the "templateName" : "xyz" on the basis of "_id" : "tenant/data/EMAIL/ENGLISH"
I have tried these queries but got no success
db.getCollection('data').updateOne({"_id": "tenant/data/EMAIL/ENGLISH"},
{$set : { "template.$.templateName" : "XYZ"}}); 
db.getCollection('data').updateOne({"_id": "tenant/data/EMAIL/ENGLISH"},
{$set : { "template.templateName" : "XYZ"}}); 
Any help will be appreciated.
I have used positional-all operator to update the array.
Here is the query:
db.sample.update(
{
"_id": "tenant/data/EMAIL/ENGLISH"
},
{
$set:{
"template.$[].templateName":"XYZ"
}
}
)
Output
{
"_id" : "tenant/data/EMAIL/ENGLISH",
"tenantId" : "tenant2",
"channelType" : "EMAIL",
"template" : [
{
"_id" : "1",
"templateName" : "XYZ",
"effectiveStartDate" : ISODate("2017-01-01T12:00:00Z"),
"modifiedDate" : ISODate("2017-06-02T22:08:55.782Z"),
"active" : false
}
]
}
hope this will help :)

Mongodb Aggregate query to groovy script

I am new to groovy scripting. I want to convert mongodb aggregate query to groovy script to query mongodb. Below is the mongodb query i want to change to groovy script:
db.VERISK_METADATA_COLLECTION.aggregate([
{ "$match":{contentType:"FRM"}},
{ "$project":{ "appCount": {$size:"$applicability"}}},
{ "$group": { "_id":null, Total: {$sum:"$appCount" } }},
{ "$project": {Total:1,"_id":0}}
])
Below is one sample record I am writing this query for:
{
"_id" : "04c64247-7030-4b0e-a2f9-da77d27b8667",
"_class" : "com.mongodb.BasicDBObject",
"documentType" : "doc",
"stateType" : "AZ",
"availabilityDate" : "",
"multiState" : "false",
"language" : "E",
"title" : "ARIZONA LIMITED EXCLUSION OF ACTS OF TERRORISM (OTHER THAN CERTIFIED ACTS OF TERRORISM); CAP ON LOSSES FROM CERTIFIED ACTS OF TERRORISM; COVERAGE FOR CERTAIN FIRE LOSSES",
"displayFormNumber" : "FP 10 53 09 05",
"mandatory" : "N",
"client_id" : "VERISK_001",
"ignored_record_type" : "new_publish_insert",
"formLobType" : "FR",
"formNumber" : "FP10530905",
"job_queue_id" : "f8ac839f-24ee-4063-bc3c-7ed00eb91f11",
"contentType" : "FRM",
"directoryName" : "FRFORMS",
"formsType" : "E",
"objectTypeCode" : "13",
"documentName" : "FP10539O",
"doc_id" : [
"f3f528e2-32ca-49f8-b287-b436befae779"
],
"update_date" : "2017-12-27 21:05:21.189 EST",
"earliestEffectiveDate_dt" : "2005-09-01T00:00:00Z",
"formStatus" : "H",
"applicability" : [
{
"filingId_dbValue_str" : "CL-2005-OFOTR",
"jurisdiction" : "AZ",
"withDrawnDate" : "2008-10-01T00:00:00Z",
"filingId" : "CL-2005-OFOTR",
"derivedFrom" : "",
"id" : "0ef65042-6b35-460e-b12a-46766c64ff27",
"circularNumber" : "LI-FR-2005-121",
"lob" : "FR",
"effectiveDate" : "2005-09-01T00:00:00Z",
"circularDate" : "2005-07-15T00:00:00Z"
}
],
"created_date" : "2017-12-27 21:05:21.106 EST",
"uri" : "VERISK_001/FRM/FP10530905"
}

MongoDB between date range query - nested property

How to write query to return object between dates? Query should search nested property. I use $gte and $lte but it doesn't seem to work as I expected. I want to return 'task' object which has got history.startTime between two dates.
db.tasks.find({'history.startTime' : { '$gte': ISODate("2017-02-04T00:00:00.000Z"), '$lt': ISODate("2017-02-05T23:00:00.000Z")} }).pretty()
{
"_id" : ObjectId("588f53c5d00baa2558fd56ae"),
"desc" : "test3",
"category" : "Category1",
"project" : "Project1",
"_creator" : "582afb3800c1bc1f203edf39",
"history" : [
{
"startTime" : ISODate("2017-02-06T11:49:42.570Z"),
"stopTime" : ISODate("2017-02-06T11:49:45.725Z"),
"_id" : ObjectId("589862d9449b4629f8dbaba7"),
"dt" : 3.155
},
{
"startTime" : ISODate("2017-02-06T08:53:53.086Z"),
"stopTime" : ISODate("2017-02-06T11:47:58.098Z"),
"_id" : ObjectId("5898626e449b4629f8dbaba6"),
"dt" : 10445.012
},
{
"startTime" : ISODate("2017-01-30T15:30:46.287Z"),
"stopTime" : ISODate("2017-01-30T15:32:52.979Z"),
"_id" : ObjectId("588f5c2cd00baa2558fd56b0"),
"dt" : 126.692
},
{
"startTime" : ISODate("2017-01-30T13:55:09.738Z"),
"stopTime" : ISODate("2017-01-30T14:55:13.974Z"),
"_id" : ObjectId("588f53d1d00baa2558fd56af"),
"dt" : 3604.236
}
],
"isCompleted" : false,
"isPerforming" : false,
"duration" : 14179.095000000001,
"updated" : ISODate("2017-02-06T11:49:45.725Z"),
"creationDate" : ISODate("2017-01-30T14:55:01.045Z"),
"__v" : 4
}
It is an array. Your query won't work. You have to use $elemMatch.
db.tasks.find({
'history': {
$elemMatch: {
startTime: {
$gte: ISODate("2017-02-04T00:00:00.000Z"),
$lte: ISODate("2017-02-05T23:00:00.000Z")
}
}
}
});

MongoDB $lookup on array of object

I have 2 collections structured as below. I have tried $lookup to get the result but I am not getting any result because of my local and foreign fields are in array of object.
Below is my structure:
{
"_id" : ObjectId("5795a3531d3f3afc19caefef"),
"name" : "category1",
"updatedAt" : "1469431592786",
"resources" : [
{
"_id" : ObjectId("5791be003fa3bedc15d3adde"),
"title" : "resource1",
"availability" : false
},
{
"_id" : ObjectId("5795a3771d3f3afc19caeff0"),
"title" : "resource2",
"availability" : true
}
]
}
Above "categories" schema have resources array of object. this resource _id is stored in bookings collection in following way:
"booking":
{
"_id" : ObjectId("57960aa8000ca7a46b7ef683"),
"name" : "1469491200000",
"__v" : 0,
"schedule" : [
{
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep",
"_id" : ObjectId("57960aa8f9f9951c1fc923b1")
},
{
"resourceId" : ObjectId("5791be003fa3bedc15d3bddz"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "mr3",
"_id" : ObjectId("57960aa8f9f9951c1fc923b2")
},
{
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep23",
"_id" : ObjectId("57960aa8f9f9951c1fc923b3")
}
]
}
Now I want to get all the schedule of booking collection with their resource information.I want to fetch resources from categories table on the basis of booking schedule.
Desired output:
[
{
"name" : "1469491200000",
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"resourceTitle":"title",
"availability":false,
"bookings": [
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep",
"_id" : ObjectId("57960aa8f9f9951c1fc923b1")
},
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep23",
"_id" : ObjectId("57960aa8f9f9951c1fc923b3")
}
]
},
{
"name" : "1469491200000",
"resourceId" : ObjectId("5791be003fa3bedc15d3bddz"),
"resourceTitle":"mr3",
"availability":false,
"bookings": [
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "mr3",
"_id" : ObjectId("57960aa8f9f9951c1fc923b2")
}
]
}
]
Help me to get this desired result.
Thanks.

Get document based on multiple criteria of embedded collection

I have the following document, I need to search for multiple items from the embedded collection"items".
Here's an example of a single SKU
db.sku.findOne()
{
"_id" : NumberLong(1192),
"description" : "Uploaded via CSV",
"items" : [
{
"_id" : NumberLong(2),
"category" : DBRef("category", NumberLong(1)),
"description" : "840 tag visual",
"name" : "840 Visual Mini Round",
"version" : NumberLong(0)
},
{
"_id" : NumberLong(7),
"category" : DBRef("category", NumberLong(2)),
"description" : "Maxi",
"name" : "Maxi",
"version" : NumberLong(0)
},
{
"_id" : NumberLong(11),
"category" : DBRef("category", NumberLong(3)),
"description" : "Button",
"name" : "Button",
"version" : NumberLong(0)
},
{
"_id" : NumberLong(16),
"category" : DBRef("category", NumberLong(4)),
"customizationFields" : [
{
"_class" : "CustomizationField",
"_id" : NumberLong(1),
"displayText" : "Custom Print 1",
"fieldName" : "customPrint1",
"listOrder" : 1,
"maxInputLength" : 12,
"required" : false,
"version" : NumberLong(0)
},
{
"_class" : "CustomizationField",
"_id" : NumberLong(2),
"displayText" : "Custom Print 2",
"fieldName" : "customPrint2",
"listOrder" : 2,
"maxInputLength" : 17,
"required" : false,
"version" : NumberLong(0)
}
],
"description" : "2 custom lines of farm print",
"name" : "Custom 2",
"version" : NumberLong(2)
},
{
"_id" : NumberLong(20),
"category" : DBRef("category", NumberLong(5)),
"description" : "Color Red",
"name" : "Red",
"version" : NumberLong(0)
}
],
"skuCode" : "NF-USDA-XC2/SM-BC-R",
"version" : 0,
"webCowOptions" : "840miniwithcust2"
}
There are repeat items.id throughout the embedded collection. Each Sku is made up of multiple items, all combinations are unique, but one item will be part of many Skus.
I'm struggling with the query structure to get what I'm looking for.
Here are a few things I have tried:
db.sku.find({'items._id':2},{'items._id':7})
That one only returns items with the id of 7
db.sku.find({items:{$all:[{_id:5}]}})
That one doesn't return anything, but it came up when looking for solutions. I found about it in the MongoDB manual
Here's an example of a expected result:
sku:{ "_id" : NumberLong(1013),
"items" : [ { "_id" : NumberLong(5) },
{ "_id" : NumberLong(7) },
{ "_id" : NumberLong(12) },
{ "_id" : NumberLong(16) },
{ "_id" :NumberLong(2) } ] },
sku:
{ "_id" : NumberLong(1014),
"items" : [ { "_id" : NumberLong(5) },
{ "_id" : NumberLong(7) },
{ "_id" : NumberLong(2) },
{ "_id" : NumberLong(16) },
{ "_id" :NumberLong(24) } ] },
sku:
{ "_id" : NumberLong(1015),
"items" : [ { "_id" : NumberLong(5) },
{ "_id" : NumberLong(7) },
{ "_id" : NumberLong(12) },
{ "_id" : NumberLong(2) },
{ "_id" :NumberLong(5) } ] }
Each Sku that comes back has both a item of id:7, and id:2, with any other items they have.
To further clarify, my purpose is to determine how many remaining combinations exist after entering the first couple of items.
Basically a customer will start specifying items, and we'll weed it down to the remaining valid combinations. So Sku.items[0].id=5 can only be combined with items[1].id=7 or items[1].id=10 …. Then items[1].id=7 can only be combined with items[2].id=20 … and so forth
The goal was to simplify my rules for purchase, and drive it all from the Sku codes. I don't know if I dug a deeper hole instead.
Thank you,
On the part of extracting the sku with item IDs 2 and 7, when I recall correctly, you have to use $elemMatch:
db.sku.find({'items' :{ '$all' :[{ '$elemMatch':{ '_id' : 2 }},{'$elemMatch': { '_id' : 7 }}]}} )
which selects all sku where there is each an item with _id 2 and 7.
You can use aggregation pipelines
db.sku.aggregate([
{"$unwind": "$sku.items"},
{"$group": {"_id": "$_id", "items": {"$addToSet":{"_id": "$items._id"}}}},
{"$match": {"items._id": {$all:[2,7]}}}
])