我需要执行mongoDB查询以获取日期之间的用户状态。
这是一个文档示例:
{
"_id" : ObjectId("538efd918163b19307c59e8e"),
"username" : "admin",
"hashedPassword" : "9qm4ufCPOCeU4AoBIMCJyf8oIvs8vWUYKIbImhc1N9HJrRKzCwCbeGNBsuOWnQ2kMbM635KmingRkn31wvHPQ/1bvs8Msg2rUchybaVvFmpy15A9Pnhb1BDHSLPftn0v8mSyhZQuOpP7Goirg07CGDPvJQqhN6oH6g0+iBTliAs=",
"salt" : "EHLY4edLmrq7Nj4zRqh7Loow/O34pHNiWQ1i4vo8+SJTl82phMokAyTSr4MNKBeMMhJgCof1uK+3++PlXp5Y3I0SL3XkzJsSWG9K5oXJCE7B3j0Kazj4IlAllOEcXwMeuBVTnTgnBi9pUqdWyDysHG893oMVmr3VizycL/Iz484=",
"realName" : "Administrator",
"roles" : [
"admin",
"operator",
"technician"
],
"status" : [],
"states" : [
{
"status" : "vacances",
"date" : ISODate("2014-06-09T11:42:02.756Z")
},
{
"status" : "busy",
"date" : ISODate("2014-06-09T11:42:03.443Z")
},
{
"status" : "eating",
"date" : ISODate("2012-06-09T11:42:04.080Z")
},
{
"status" : "busy",
"date" : ISODate("2014-06-09T11:49:53.765Z")
},
{
"status" : "vacances",
"date" : ISODate("2014-06-09T11:49:54.402Z")
},
{
"status" : "eating",
"date" : ISODate("2014-06-09T11:49:56.409Z")
},
{
"status" : "resting",
"date" : ISODate("2014-06-09T11:49:57.114Z")
},
{
"status" : "eating",
"date" : ISODate("2014-06-09T12:24:38.880Z")
},
{
"status" : "busy",
"date" : ISODate("2014-06-09T14:51:13.440Z")
},
{
"status" : "free",
"date" : ISODate("2014-06-09T14:51:20.940Z")
},
{
"status" : "vacances",
"date" : ISODate("2014-06-12T11:05:36.448Z")
},
{
"status" : "busy",
"date" : ISODate("2014-06-12T11:05:37.425Z")
}
]
}
然后,想要获取日期之间的状态,我有这个查询:
var collection = db.collection('users');
collection.aggregate([
{$match: {$and: [
{ _id: new ObjectID(id)},
{ 'states.date': { $gt: new Date(from), $lte: new Date(to) }}
]}},
{$unwind: "$states"},
{$sort: {"states.date": -1}},
{$group: {_id: "$_id", states: {$push: "$states"}}}
], function (e, doc) {
if (e) {
error(e);
}
success(doc);
});
结果是错误的,因为返回我用户的所有状态,不仅仅是在日期查询之间..如何减少mongodb查询中的响应?
答案 0 :(得分:1)
您应该在$unwind
阵列后过滤文档。您的第一个匹配项将匹配整个文档,但不会过滤掉数组中的文档:
var collection = db.collection('users');
collection.aggregate([
{$match: { _id: new ObjectID(id) } },
{$unwind: "$states"},
{$match: { 'states.date': { $gt: new Date(from), $lte: new Date(to) }}},
{$sort: {"states.date": -1}},
{$group: {_id: "$_id", states: {$push: "$states"}}}
], function (e, doc) {
if (e) {
error(e);
}
success(doc);
});
修改强>
如果您正在寻找特定用户,也无需在第一个$match
中搜索日期范围。仅按_id
进行过滤将在该字段上使用默认索引,并且速度会快得多。
答案 1 :(得分:0)
您的第一个$match
条件仅匹配文档而不匹配数组成员。到"过滤"你需要在$match
之后实际$unwind
:
collection.aggregate([
{$match: {$and: [
{ _id: new ObjectID(id)},
{ 'states.date': { $gt: new Date(from), $lte: new Date(to) }}
]}},
{$unwind: "$states"},
{$match: {$and: [
{ 'states.date': { $gt: new Date(from), $lte: new Date(to) }}
]}},
{$sort: {"states.date": -1}},
{$group: {_id: "$_id", states: {$push: "$states"}}}
], function (e, doc) {
if (e) {
error(e);
}
success(doc);
});