Reputation: 731
I have a collection documents looks like:
{
"_id" : ObjectId("560ba1e86db58e34168b456a"),
"object_id" : "1722224",
"user" : {
"id" : null,
"cookie" : "sEnAl9DdPHyTdmxYU3E23g"
},
"createddate" : ISODate("2015-09-30T11:48:40.000+03:00"),
"activity" : [
{
"name" : "Map click",
"selector" : "#toMap",
"event" : "click",
"time" : ISODate("2015-09-30T12:30:59.000+03:00")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T11:48:47.687+03:00")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T15:34:12.000+03:00")
}
]
}
I need to pass to mongodb range of dates and get a day-by-day result that contains: 1. Date 2. Set of selectors clicked that date and count of that clicks:
{
"date" : ISODate("2015-09-29T00:00:00.000+03:00"),
"selectors" : [
{"#toMap" : 100},
{"#jsn-showContacts" : 200}
]
},
{
"date" : ISODate("2015-09-30T00:00:00.000+03:00"),
"selectors" : [
{"#toMap" : 50},
{"#jsn-showContacts" : 80},
{"#toOrder" : 10}
]
}
The result should count click once for every document, for example if i have two #showContacts-Min
clicks in one document:
"activity" : [
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T11:48:47.687+03:00")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T15:34:12.000+03:00")
}
]
it have to be couned once.
Is it really possible to do on DB side as one query or should it be implemented on application side with multiple db queries?
Upvotes: 1
Views: 82
Reputation: 1073
It is well possible to get desired result using single query.I'm assuming your "selector" values are prior know so that it can be hard coded in MongoDB query.
Here I have created sample documents as per your schema :
> db.a.find().pretty()
{
"_id" : ObjectId("560ba1e86db58e34168b456a"),
"object_id" : "1722224",
"user" : {
"id" : null,
"cookie" : "sEnAl9DdPHyTdmxYU3E23g"
},
"createddate" : ISODate("2015-09-30T08:48:40Z"),
"activity" : [
{
"name" : "Map click",
"selector" : "#toMap",
"event" : "click",
"time" : ISODate("2015-09-30T09:30:59Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T08:48:47.687Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T12:34:12Z")
}
]
}
{
"_id" : ObjectId("560c19550e45be0a683ccd01"),
"object_id" : "1722224",
"user" : {
"id" : null,
"cookie" : "sEnAl9DdPHyTdmxYU3E23g"
},
"createddate" : ISODate("2015-10-30T08:48:40Z"),
"activity" : [
{
"name" : "Map click",
"selector" : "#toMap",
"event" : "click",
"time" : ISODate("2015-09-30T09:30:59Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T08:48:47.687Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T12:34:12Z")
}
]
}
{
"_id" : ObjectId("560c19750e45be0a683ccd02"),
"object_id" : "1722224",
"user" : {
"id" : null,
"cookie" : "sEnAl9DdPHyTdmxYU3E23g"
},
"createddate" : ISODate("2015-10-30T08:48:40Z"),
"activity" : [
{
"name" : "Map click",
"selector" : "#toMap",
"event" : "click",
"time" : ISODate("2015-09-30T09:30:59Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T08:48:47.687Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T12:34:12Z")
}
]
}
{
"_id" : ObjectId("560c19940e45be0a683ccd03"),
"object_id" : "1722224",
"user" : {
"id" : null,
"cookie" : "sEnAl9DdPHyTdmxYU3E23g"
},
"createddate" : ISODate("2016-01-30T08:48:40Z"),
"activity" : [
{
"name" : "Map click",
"selector" : "#toMap",
"event" : "click",
"time" : ISODate("2015-09-30T09:30:59Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T08:48:47.687Z")
},
{
"name" : "Show contacts (main block)",
"selector" : "#jsn-showContacts",
"event" : "click",
"time" : ISODate("2015-09-30T12:34:12Z")
}
]
}
Below query will give your result.Here Count is selected without considering duplicate values within a single document
>db.a.aggregate([{"$match":
{createddate:{"$gt": ISODate("2014-10-30T11:48:40.000+03:00"),
"$lt":ISODate("2016-10-30T11:48:40.000+03:00")}}},
{'$group':{"_id":{"date":"$createddate"},
"#toMap":{"$sum":{"$cond":{"if":{"$anyElementTrue":{
"$map":{"input":"$activity",
"as":"act",
"in":{"$eq": ["$$act.selector","#toMap"]}}}},"then":1,"else":0}}},
"#jsn-showContacts":{"$sum":{"$cond":{"if":{"$anyElementTrue":{
"$map":{
"input":"$activity",
"as":"act",
"in":{"$eq":["$$act.selector","#jsn- showContacts"]}}}},"then":1,"else":0}}}}}])
//Result:
{ "_id" : { "date" : ISODate("2016-01-30T08:48:40Z") }, "#toMap" : 1, "#jsn-showContacts" : 1 }
{ "_id" : { "date" : ISODate("2015-10-30T08:48:40Z") }, "#toMap" : 2, "#jsn-showContacts" : 2 }
{ "_id" : { "date" : ISODate("2015-09-30T08:48:40Z") }, "#toMap" : 1, "#jsn-showContacts" : 1 }
Selectors are not in an array in Result,But I hope this will do.You can use $project as last pipelie stage to modify result schema
Upvotes: 2