MongoDB / Mongoose – 按date查询对象数组

我有以下指标集合:

{ name: "Hello", values: [ { value: 2629, date: "2016-10-28T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee8" }, { value: 1568, date: "2016-10-29T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee7" }, { value: 1547, date: "2016-10-30T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee6" }, { value: 1497, date: "2016-10-31T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee5" }, { value: 3031, date: "2016-11-01T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee4" }, { value: 2559, date: "2016-11-02T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee3" }, { value: 2341, date: "2016-11-03T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee2" }, { value: 2188, date: "2016-11-04T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee1" }, { value: 3280, date: "2016-11-05T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdee0" }, { value: 4638, date: "2016-11-06T07:00:00.000Z", _id: "58453abfef7aaa15ac1fdedf" } ] }, .... more of the same 

我想得到的是自定义date范围之间的所有值。 我已经尝试了以下查询,但我仍然得到了返回的整个值数组:

 { name: "Hello", values: { $elemMatch: { date: { $lt: "2016-11-03T07:00:00.000Z", $gt: "2016-10-28T07:00:00.000Z" } } } } 

也许我以错误的格式保存了我的date? 任何帮助将不胜感激。

您可以运行使用values数组上的$filter运算符的聚合pipe道。 下面的mongo shell查询演示了这一点:

 var start = new Date("2016-10-28T07:00:00.000Z"), end = new Date("2016-11-03T07:00:00.000Z"); db.metrics.aggregate([ { "$match": { "name": "Hello", "values.date": { "$gt": start, "$lt": end } } }, { "$project": { "name": 1, "values": { "$filter": { "input": "$values", "as": "value", "cond": { "$and": [ { "$gt": [ "$$value.date", start ] }, { "$lt": [ "$$value.date", end ] } ] } } } } } ]) 

示例输出

 /* 1 */ { "_id" : ObjectId("5845453145fda1298fa50db9"), "name" : "Hello", "values" : [ { "value" : 1568, "date" : ISODate("2016-10-29T07:00:00.000Z"), "_id" : ObjectId("58453abfef7aaa15ac1fdee7") }, { "value" : 1547, "date" : ISODate("2016-10-30T07:00:00.000Z"), "_id" : ObjectId("58453abfef7aaa15ac1fdee6") }, { "value" : 1497, "date" : ISODate("2016-10-31T07:00:00.000Z"), "_id" : ObjectId("58453abfef7aaa15ac1fdee5") }, { "value" : 3031, "date" : ISODate("2016-11-01T07:00:00.000Z"), "_id" : ObjectId("58453abfef7aaa15ac1fdee4") }, { "value" : 2559, "date" : ISODate("2016-11-02T07:00:00.000Z"), "_id" : ObjectId("58453abfef7aaa15ac1fdee3") } ] } 

对于MongoDB 3.0,以下解决方法适用:

 var start = new Date("2016-10-28T07:00:00.000Z"), end = new Date("2016-11-03T07:00:00.000Z"); db.metrics.aggregate([ { "$match": { "name": "Hello", "values.date": { "$gt": start, "$lt": end } } }, { "$project": { "name": 1, "values": { "$setDifference": [ { "$map": { "input": "$values", "as": "value", "in": { "$cond": [ { "$and": [ { "$gt": [ "$$value.date", start ] }, { "$lt": [ "$$value.date", end ] } ] }, "$$value", false ] } } }, [false] ] } } } ]) 

MongoDB 2.2+中的聚合框架提供了Map / Reduce的替代scheme。 $unwind运算符可以用来将你的values数组分隔成一个可以匹配的文档stream:

 db.tmp.aggregate( // Start with a $match pipeline which can take advantage of an index and limit documents processed { $match : { name: "Hello", "values.date": { $lt: "2016-11-03T07:00:00.000Z", $gt: "2016-10-28T07:00:00.000Z" } }}, { $unwind : "$values" }, { $match : { name: "Hello", "values.date": { $lt: "2016-11-03T07:00:00.000Z", $gt: "2016-10-28T07:00:00.000Z" } }} ) 

示例输出

 { "_id":ObjectId("5845432720ce37bdc7e9ca1c"), "name":"Hello", "values":{ "value":1568, "date":"2016-10-29T07:00:00.000Z", "_id":"58453abfef7aaa15ac1fdee7" } },{ "_id":ObjectId("5845432720ce37bdc7e9ca1c"), "name":"Hello", "values":{ "value":1547, "date":"2016-10-30T07:00:00.000Z", "_id":"58453abfef7aaa15ac1fdee6" } },{ "_id":ObjectId("5845432720ce37bdc7e9ca1c"), "name":"Hello", "values":{ "value":1497, "date":"2016-10-31T07:00:00.000Z", "_id":"58453abfef7aaa15ac1fdee5" } },{ "_id":ObjectId("5845432720ce37bdc7e9ca1c"), "name":"Hello", "values":{ "value":3031, "date":"2016-11-01T07:00:00.000Z", "_id":"58453abfef7aaa15ac1fdee4" } },{ "_id":ObjectId("5845432720ce37bdc7e9ca1c"), "name":"Hello", "values":{ "value":2559, "date":"2016-11-02T07:00:00.000Z", "_id":"58453abfef7aaa15ac1fdee3" } }