我正在努力研究MongoDb以获得理想的结果。
我的收藏品如下:
{
_id: ...
place: 1
city: 6
user: 306
createDate: 2014-08-10 12:20:21,
lastUpdate: 2014-08-14 10:11:01,
data: [
{
customId4: 4,
entryDate: 2014-07-12 12:01:11,
exitDate: 2014-07-12 13:12:12
},
{
customId4: 4,
entryDate: 2014-07-14 00:00:01,
},
{
customId4: 5,
entryDate: 2014-07-15 11:01:11,
exitDate: 2014-07-15 11:05:15
},
{
customId4: 5,
entryDate: 2014-07-22 21:01:11,
exitDate: 2014-07-22 21:23:22
},
{
customId4: 4,
entryDate: 2014-07-23 14:00:11,
},
{
customId4: 4,
entryDate: 2014-07-29 22:00:11,
exitDate: 2014-07-29 23:00:12
},
{
customId4: 5,
entryDate: 2014-08-12 12:01:11,
exitDate: 2014-08-12 13:12:12
},
]
}
所以我想要实现的是满足特定间隔要求且同时设置了entryDate和exitDate值的数组数据。
例如,如果我按间隔" 2014-07-23 00:00:00到2014-08-31 00:00:00"我希望结果如下:
{
result: [
{
_id: {
place: 1,
user: 306
},
city: 6,
place: 1,
user: 306,
data: [
{
customMap: 4,
entryDate: 2014-07-22 21:01:11,
exitDate: 2014-07-22 21:23:22
},
{
customId4: ,
entryDate: 2014-07-29 22:00:11,
exitDate: 2014-07-29 23:00:12
},
]
}
],
ok: 1
}
我的自定义mongodb查询看起来像(from,to和placeIds是正确配置的变量)
db.myColl.aggregate(
{ $match: {
'user': 1,
'data.entryDate': { $gte: from, $lte: to },
'place': { $in: placeIds },
}},
{ $unwind : "$data" },
{ $project: {
'city': 1,
'place': 1,
'user': 1,
'lastUpdate': 1,
'data.entryDate': 1,
'data.exitDate': 1,
'data.custom': 1,
fromValid: { $gte: ["$'data.entryDate'", from]},
toValid: { $lte: ["$'data.entryDate'", to]}}
},
{ $group: {
'_id': {'place': '$place', 'user': '$user'},
'city': {'$first': '$city'},
'place': {'$first': '$place'},
'user': {'$first': '$user'},
'data': { '$push': '$data'}
}}
)
但这并没有按照我想要的方式进行过滤,因为它会输出满足$ match操作数条件的每个文档,在$ project操作数内我无法定义条件(我不知道这是不是是如何在mongoDB中完成的)
提前致谢!
答案 0 :(得分:1)
你走在正确的轨道上,但聚合“管道”可能会缺少的就是“|”在unix shell中的管道操作符可以将管道阶段“链接”在一起,就像链接命令一样。
所以实际上可以有第二个$match
管道阶段为你做过滤:
db.myColl.aggregate([
{ "$match": {
"user": 1,
"data.entryDate": { "$gte": from, "$lte": to },
"place": { "$in": "placeIds" },
}},
{ "$unwind": "$data" },
{ "$match": {
"data.entryDate": { "$gte": from, "$lte": to },
}},
{ "$group": {
"_id": "$_id",
"place": { "$first": "$place" },
"city": { "$first": "$city" },
"user": { "$first": "$user" },
"data": { "$push": "$data" }
}}
])
使用文档的实际_id
作为分组键,假定您希望文档返回但只是使用过滤后的数组。
从MongoDB 2.6开始,只要匹配的数组元素是唯一的,您就可以使用$project
和$map
在内执行相同的操作$setDifference
**运营商:
db.myColl.aggregate([
{ "$match": {
"user": 1,
"data.entryDate": { "$gte": from, "$lte": to },
"place": { "$in": "placeIds" },
}},
{ "$project": {
"place": 1,
"city": 1,
"user": 1,
"data": {
"$setDifference": [
{ "$map": {
"input": "$data",
"as": "el",
"in": {"$cond": [
{ "$and": [
{ "$gte": [ "$$el.entryDate", from ] },
{ "$lte": [ "$$el.entryDate", to ] }
]},
"$$el",
false
]}
}},
[false]
]
}
}}
])
通过处理每个数组元素并评估它是否符合条件,这是相同的逻辑。如果是,则返回元素内容,否则返回false
。 $setDifference
会过滤掉所有false
值,以便只保留匹配的值。