以下是一些插入语句
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 }
]
}
此处按endDt
字段排序,但endDt
字段为true的最后active
条记录将包含以前所有"有效"字段中的真实记录。
我认为,第二种情况是不可能的。
答案 0 :(得分:0)
第一个很简单,你可以这样做:
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")
]
}
第二个可能是可行的,但您需要更准确地定义您想要返回的内容。
答案 1 :(得分:0)
您可以使用group命令......
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 docs
了解更多信息答案 2 :(得分:0)
案例1 可以返回确切的结果集。但案例2 不是有效的文件。
实际上,我的朋友道格在blog给了我答案。我只是把它复制到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
}
]
}