如何在MongoDB中根据布尔字段对查询进行分组,并通过布尔值分别检索所有记录



以下是一些插入语句

db.users.insert({ courseId: 1, stDt: new Date(2014, 01, 01), endDt: new Date(2014, 01, 20), active: false }); 
db.users.insert({ courseId: 1, stDt: new Date(2014, 01, 25), endDt: new Date(2014, 02, 10), active: false }); 
db.users.insert({ courseId: 1, stDt: new Date(2014, 02, 25), endDt: new Date(2014, 03, 10), active: true }); 
db.users.insert({ courseId: 1, stDt: new Date(2014, 02, 28), endDt: new Date(2014, 06, 10), active: true }); 
db.users.insert({ courseId: 1, stDt: new Date(2014, 02, 25), endDt: new Date(2014, 02, 30), active: false }); 
db.users.insert({ courseId: 1, stDt: new Date(2014, 05, 25), endDt: new Date(2014, 10, 30), active: false }); 
db.users.insert({ courseId: 1, stDt: new Date(2013, 10, 01), endDt: new Date(2014, 08, 10), active: true }); 
db.users.insert({ courseId: 1, stDt: new Date(2014, 09, 01), endDt: new Date(2014, 11, 30), active: false }); 

案例1:我们可以从上面插入的值创建以下结果集吗?在这里,所有将"活动"字段设置为 true 和 false 的结果都按"endDt"字段排序,该字段通过单个查询单独检索。

{ "result" : { 
    true : [ 
      { endDt: new Date(2014, 03, 10), active: true }, 
      { endDt: new Date(2014, 06, 10), active: true },  
      { endDt: new Date(2014, 08, 10), active: true }, 
   ],
   false: [ 
      { endDt: new Date(2014, 01, 20), active: false }, 
      { endDt: new Date(2014, 02, 10), active: false }, 
      { endDt: new Date(2014, 02, 30), active: false }, 
      { endDt: new Date(2014, 10, 30), active: false }, 
      { endDt: new Date(2014, 11, 30), active: false } 
   ]
  }
} 

可以通过单个查询来完成吗?

案例2:我们可以做以下结果集吗?

{ "result" : [ 
    { endDt: new Date(2014, 01, 20), active: false }, 
    { endDt: new Date(2014, 02, 10), active: false }, 
    { endDt: new Date(2014, 02, 30), active: false }, 
    [   
        { endDt: new Date(2014, 03, 10), active: true }, 
        { endDt: new Date(2014, 06, 10), active: true },    
        { endDt: new Date(2014, 08, 10), active: true } 
    ], 
    { endDt: new Date(2014, 10, 30), active: false }, 
    { endDt: new Date(2014, 11, 30), active: false } 
  ]
} 

这里按字段排序endDtactive字段 true 的最后endDt条记录将包含所有先前"活动"字段 true 记录的数组。

我认为,第二种情况是不可能的。

第一个很简单,你做这样的事情:

db.users.aggregate({$sort:{endDt:1}}, {$group:{_id:"$active", dates:{$push:"$endDt"}}})
{
    "_id" : true,
    "dates" : [
        ISODate("2014-04-10T07:00:00Z"),
        ISODate("2014-07-10T07:00:00Z"),
        ISODate("2014-09-10T07:00:00Z")
    ]
},
{
    "_id" : false,
    "dates" : [
        ISODate("2014-02-20T08:00:00Z"),
        ISODate("2014-03-10T07:00:00Z"),
        ISODate("2014-03-30T07:00:00Z"),
        ISODate("2014-11-30T08:00:00Z"),
        ISODate("2014-12-30T08:00:00Z")
    ]
}

第二个可能是可行的,但您需要更精确地定义您想要返回的内容。

你可以这样使用组命令...

db.users.aggregate({'$group' : {'_id' : '$active','endDt' : {'$addToSet' : '$endDt'}}})
{
        "result" : [
                {
                        "_id" : true,
                        "endDt" : [
                                ISODate("2014-09-09T21:00:00Z"),
                                ISODate("2014-07-09T21:00:00Z"),
                                ISODate("2014-04-09T21:00:00Z")
                        ]
                },
                {
                        "_id" : false,
                        "endDt" : [
                                ISODate("2014-12-29T21:00:00Z"),
                                ISODate("2014-11-29T21:00:00Z"),
                                ISODate("2014-03-29T21:00:00Z"),
                                ISODate("2014-03-09T21:00:00Z"),
                                ISODate("2014-02-19T21:00:00Z")
                        ]
                }
        ],
        "ok" : 1
}

您可以在 MONGO 文档中阅读更多内容

案例 1 可以返回确切的结果集。但案例 2 不是有效的文件。

实际上,答案是我的朋友道格在他的博客中给我的。我只是将其复制到SO。

这是对案例 1 的查询,它由注释解释。

db.users.aggregate([    
    // Project only what we need.
    {
        "$project": {
            "endDt": 1,
            "active": 1,
            "_id": 0
        }
    },
    // Group to true and false buckets. This will give us arrays with null.
    // We'll remove them in a bit.
    {
        "$group": {
            "_id": "$active",
            "true": {
                "$addToSet": {
                    "$cond": [
                        {"$eq": ["$active", true]},
                        "$endDt",
                        null
                    ]
                }
            },
            "false": {
                "$addToSet": {
                    "$cond": [
                        {"$eq": ["$active", false]},
                        "$endDt",
                        null
                    ]
                }
            }
        }
    },
    // We need to unwind our arrays so we can build them back up without the
    // "null" array.
    {"$unwind": "$true"},
    {"$unwind": "$false"},
    // Project out the values. This will give both a true and false key for
    // each item. This builds our arrays up with the proper endDt and
    // active values.
    {
        "$project": {
            "true": {"endDt": "$true", "active": "$_id"}, 
            "false": {"endDt": "$false", "active": "$_id"}
        }
    },
    // Project out a single value to clean up the "issue" a couple steps above.
    {
        "$project": {
            "value": {
                "$cond": [
                    {"$eq": ["$_id", true]},
                    "$true",
                    "$false"
                ]
            }
        }
    },
    // Group things up again to rebuild our arrays.
    // This adds a single "null" entry that will need to be cleaned up.
    {
        "$group": {
            "_id": null,
            "true": {
                "$addToSet": {
                     "$cond": [
                         {"$eq": ["$_id", true]},
                         "$value",
                         null
                     ]
                }
            },
            "false": {
                "$addToSet": {
                    "$cond": [
                        {"$eq": ["$_id", false]},
                        "$value",
                        null
                    ]
                }
            }
        }
    },
    // Unwind our arrays again so we can clean up one more time.
    {"$unwind": "$true"},
    {"$unwind": "$false"},
    // Match only documents where true and false are not null.
    {
        "$match": {
            "true": {"$ne": null},
            "false": {"$ne": null}
        }
    },
    // Sort our items so we can add the to the array in the correct order.
    // I'm not sure why it has to be descending order, but it works.
    {
        "$sort": {
            "true.endDt": -1,
            "false.endDt": -1
        }
    },
    // Group again to build our array.
    {
        "$group": {
            "_id": null,
            "true": {"$addToSet": "$true"},
            "false": {"$addToSet": "$false"}
        }
    },
    // Once again project out just the fields we need
    {
        "$project": {
            "true": 1,
            "false": 1,
            "_id": 0
        }
    }
])
以下是MongoDB 2.2.x

- 2.4.x中返回的结果:

{
    "result" : [
        {
            "true" : [
                {
                    "endDt" : ISODate("2014-04-10T06:00:00Z"),
                    "active" : true
                },
                {
                    "endDt" : ISODate("2014-07-10T06:00:00Z"),
                    "active" : true
                },
                {
                    "endDt" : ISODate("2014-09-10T06:00:00Z"),
                    "active" : true
                }
            ],
            "false" : [
                {
                    "endDt" : ISODate("2014-02-20T07:00:00Z"),
                    "active" : false
                },
                {
                    "endDt" : ISODate("2014-03-10T06:00:00Z"),
                    "active" : false
                },
                {
                    "endDt" : ISODate("2014-03-30T06:00:00Z"),
                    "active" : false
                },
                {
                    "endDt" : ISODate("2014-11-30T07:00:00Z"),
                    "active" : false
                },
                {
                    "endDt" : ISODate("2014-12-30T07:00:00Z"),
                    "active" : false
                }
            ]
        }
    ],
    "ok" : 1
}

在即将发布的 2.6.0 版本中,结果如下所示:

{
    "true" : [
        {
            "endDt" : ISODate("2014-04-10T06:00:00Z"),
            "active" : true
        },
        {
            "endDt" : ISODate("2014-07-10T06:00:00Z"),
            "active" : true
        },
        {
            "endDt" : ISODate("2014-09-10T06:00:00Z"),
            "active" : true
        }
    ],
    "false" : [
        {
            "endDt" : ISODate("2014-02-20T07:00:00Z"),
            "active" : false
        },
        {
            "endDt" : ISODate("2014-03-10T06:00:00Z"),
            "active" : false
        },
        {
            "endDt" : ISODate("2014-03-30T06:00:00Z"),
            "active" : false
        },
        {
            "endDt" : ISODate("2014-11-30T07:00:00Z"),
            "active" : false
        },
        {
            "endDt" : ISODate("2014-12-30T07:00:00Z"),
            "active" : false
        }
    ]
}

相关内容

  • 没有找到相关文章

最新更新