我和MongoDb打架
我有一组文档,其单个文档的结构如下
{
"_id": { "$oid": "588a931d5c98fe0f3f84d93f" },
"name": "Michele",
"type": "F",
"category": "G",
"meta":{
"code": "113835667",
"updated": {"$date": "2017-02-07T00:00:00.000Z"},
"since": {"$date": "2013-11-07T23:00:00.000Z"}
},
"data": [
{
"date": {"$date": "2013-11-07T23:00:00.000Z"},
"close": 12.23
}
... // removed
{
"date": {"$date": "2017-02-07T00:00:00.000Z"},
"close": 15.22
}
]
}
我需要实现的是返回带有匹配_id的文档,但是从数据数组中过滤出date属性不在指定时间范围内的文档。
这是我从现在开始尝试的事情
let id; //[DocumentId]
let from; //[Date]
let to; //[Date]
collection.aggregate([
{ $match: { _id: { $eq: id } } },
{ $unwind: '$data' },
{ $match: { 'data.date': { $gte: from, $lte: to } } },
{ $group: { _id: '$_id',
data: { $push: { date:'$data.date', close: '$data.close' } } } }
], ...);
这种方法的问题是我返回的文档只包含_id和数据属性[数据过滤结果正常],而我需要返回完整的可用属性集。
建议非常感谢!
答案 0 :(得分:1)
如果你可以升级到Mongo 3.4(最新的稳定版本),它可以很好地完成:
db.collection.aggregate([
//Pre-filter to have data arrays with at least one matching date
{$match: {_id: id, 'data.date': {$gte: from, $lte: to}}},
//Filter the items array
{
$addFields: {
'items': {
$filter: {
input: '$data', as: 'item', cond: {
$and: [
{$gte: ["$$item.date", from]},
{$lte: ["$$item.date", to]}
]
}
}
}
}
}
]);
如果你必须保留mongo 3.2,我唯一能想到的就是使用这样的$ ROOT:
db.collection.aggregate([
{$match: {_id: id, 'data.date': {$gte: from, $lte: to}}},
{
$project: {
'filteredData': {
$filter: {
input: '$data', as: 'item', cond: {
$and: [
{$gte: ["$$item.date", from]},
{$lte: ["$$item.date", to]}
]
}
}
},
'originalDocument': '$$ROOT'
}
}
]);
生成的对象将具有originalDocument和filteredData作为属性,您需要在服务器代码中处理它们(实际上是一个循环)。