Here is what I am working with:
{
"_id": ObjectId("53b4402ae1382335c95952d3"),
"created": ISODate("2014-07-02T10:23:54.245Z"),
"modified": ISODate("2011-11-28T10:06:25.186Z"),
"source": [{
"instances": [{
"analyst": "harry",
"date": ISODate("2014-07-02T10:23:54.242Z"),
"reference": "abb32"
},
{
"analyst": "david",
"date": ISODate("2014-07-02T10:33:02.296Z"),
"reference": "can26"
}],
"name": "Apples"
},
{
"instances": [{
"analyst": "critsAPI",
"date": ISODate("2011-11-28T10:06:25.156Z"),
"reference": "z561c"
}],
"name": "Oranges"
}],
"releasability": [],
}
What I would like is a count of every document which has an "instances date " in a certain range (lets say a month) along with a certain name. I have used two queries with "elemMatch" and unfortunately I am not getting the results I expect. Here is what I have tried using elemMatch and instances.date:
collection.find(
{
'source':
{
'$elemMatch' : {
'name':'Apples',
'instances.date' : {'$lte' : ISODate("2014-07-30T00:00:00Z") ,
'$gte' : ISODate("2014-07-01T00:00:00Z")}
}
}
}
).count()
Here is with a nested elemMatch :
collection.find(
{
'source':
{
'$elemMatch' : {
'name':'Apples',
'instances': {
'$elemMatch' : {
'date' : {'$lte' : ISODate("2014-07-30T00:00:00Z") ,
'$gte' : ISODate("2014-07-01T00:00:00Z")}
}
}
}
}
}
).count()
Thanks in advance.
I'm guessing that your are getting a count()
of 1 since the count()
method returns the number of documents, not the number of array elements.
To get a result of 2 (based on the above document) you need to use the Aggregation Framework.
Please try something like the following:
db.coll1.aggregate([ {$unwind : "$source"}, {$unwind : "$source.instances"}, {$match: { $and: [ {"source.name" : "Apples"}, {"source.instances.date" : {"$lte" : ISODate("2014-07-30T00:00:00Z")}}, {"source.instances.date" : {"$gte" : ISODate("2014-07-01T00:00:00Z")}} ] }}, {$project: { name1: "$source.name", date1: "$source.instances.date" }}, {$group : {_id: "$name1", name1: {$sum:1}}} ])and I get the following in the shell
{ "result" : [ { "_id" : "Apples", "name1" : 2 } ], "ok" : 1 }
The $unwind
breaks the array into separate docs, the $match
does the selection, the $project
defines the result fields (similar toSELECT
clause in SQL), the $group
sums the entries (similar to 'GROUP BY` in SQL)
These individual steps in the aggregation pipeline sequentially filters/transforms a result set of documents.
Hope that helps