MongoDB与elemMatch和日期字段的结果不正确

时间:2014-01-18 10:04:22

标签: mongodb mongodb-query

我有以下文件

{
    "_id" : ObjectId("52da43cd6f0a61e8a5059aaf"),
    "assignments" : [
        {
            "project" : "abc",
            "start" : ISODate("2012-12-31T18:30:00Z"),
            "end" : ISODate("2013-06-29T18:30:00Z")
        },
        {
            "project" : "efg",
            "start" : ISODate("2013-06-30T18:30:00Z"),
            "end" : ISODate("2014-03-30T18:30:00Z")
        }
    ],
    "eid" : "123",
    "name" : "n1",
    "uid" : "u1"
}

我试图通过以下查询找到在特定日期之后开始的所有作业。但返回的数据令人困惑,看起来不正确。 pl帮助我理解我做错了什么。

> db.test.find( {uid:'u1'},{ assignments: { $elemMatch: {end: {$gte: new Date(2011,5,1) } } }} ).pretty();
{
    "_id" : ObjectId("52da43cd6f0a61e8a5059aaf"),
    "assignments" : [
        {
            "project" : "abc",
            "start" : ISODate("2012-12-31T18:30:00Z"),
            "end" : ISODate("2013-06-29T18:30:00Z")
        }
    ]
}

它应该返回两个项目吗?

3 个答案:

答案 0 :(得分:2)

$elemMatch operator将结果限制为每个文档的第一个匹配数组元素。

如果要返回所有匹配的数组元素,可以使用Aggregation Framework

db.courses.aggregate(
    // Find matching documents (would benefit from an index on `{uid: 1}`)
    { $match : {
        uid:'u1'
    }},

    // Unpack the assignments array
    { $unwind : "$assignments" },

    // Find the assignments ending after given date
    { $match : {
        "assignments.end": { $gte: ISODate("2011-05-01") }
    }}
)

答案 1 :(得分:1)

$elemMatch以下列方式限制预测。 假设您有一个包含这些文档的集合:

{ "_id" : 1, "prices" : [ 50, 60, 70 ] }
{ "_id" : 2, "prices" : [ 80, 90, 100 ] }
db.t.find({},{'prices':{$elemMatch:{$gt:50}}})

返回:

{ "_id" : 1, "prices" : [ 60 ] }
{ "_id" : 2, "prices" : [ 80 ] }

投影将缩减为匹配的第一个元素,而不是匹配的所有元素。 如果你期待这样的结果:

{ "_id" : 1, "prices" : [ 60,70] }
{ "_id" : 2, "prices" : [ 80, 90, 100 ] }

仅支持$elemMatch$$slice的投影无法实现。 例如,您可以在投影或任何其他智能投影中使用$ all。

如果您想整理文档,匹配,过滤,投影以及展开和风(通过分组)。

aggregate([ {$unwind:'$prices'},{$match:{'prices':{$gt:50}}},{$group:{_id:'$_id',prices:{$push:'$prices'}}}])

这将导致我们正在寻找的东西。

{ "_id" : 2, "prices" : [ 80, 90, 100 ] }
{ "_id" : 1, "prices" : [ 60, 70 ] }

您可以采用此模式并根据您的具体情况使用它。

答案 2 :(得分:0)

使用该查询,您正在使用uid = u1搜索文档并将结果投影到仅显示日期大于Date(2011,5,1)的第一个元素。查看$elemMatch projection operator

我认为你需要这样的东西:

db.test.find( 
{
    uid:'u1'
    "assignments.end": {$gte: new Date(2011,5,1)} 
}).pretty();