在数组Mongodb中搜索日期



我有很多像这样的文档:

    { 
    "_id" : ObjectId("54a94200aa76d3db6cd51977"), 
    "URL" : "http://...", 
    "Statistics" : [
        {
            "Date" : ISODate("2010-05-18T18:07:29.000+0000"), 
            "Clicks" : NumberInt(250), 
        }, 
        {
            "Date" : ISODate("2010-05-21T12:06:41.000+0000"), 
            "Clicks" : NumberInt(165), 
        }, 
        {
            "Date" : ISODate("2010-05-30T08:37:50.000+0000"), 
            "Clicks" : NumberInt(263), 
        } 
    ]
}

我的查询如下:

db.clicks.aggregate([
    { $match : 'Statistics.Date' : { $gte: new Date("2010-05-18T00:00:00.000Z"), $lte: new Date("2010-05-18T23:59:59.999Z") } },
    { $unwind' => '$Statistics' },
    { $group : { _id : { year : { $year : '$Statistics.Date' }, month : { $month : '$Statistics.Date' }, day : { $dayOfMonth : '$Statistics.Date' } }, Clicks : { $sum : '$Statistics.Clicks' } },
    { $sort : { _id : 1 } }
])

当我试图总结特定日期的点击量时,它会给我所有的日期,而不是只有一个。我做错了什么?提前谢谢。

编辑1:由于该集合中有超过80000个文档,我无法在$match之前执行$unwind。此外,担心这不是一个好主意,因为这会使查询速度慢于必要的速度。其中大量的文档和数据是我必须使用$sum的原因。我上面制作的文档只是一个例子,只有结构与我的项目相同。

上面的查询给了我这样的smth:

{
    "_id" : [
        { 
        "year" : 2010,
        "month" : 5,
        "day" : 18
        }
    ],
    "Clicks" : 250
},
{
    "_id" : [
        { 
        "year" : 2010,
        "month" : 4,
        "day" : 21
        }
    ],
    "Clicks" : 165
},
{
    "_id" : [
        { 
        "year" : 2010,
        "month" : 5,
        "day" : 30
        }
    ],
    "Clicks" : 263
}

如果我不使用$group,我也必须使用$limit,因为查询将超过16MB,否则:

db.clicks.aggregate([
        { $match : 'Statistics.Date' : { $gte: new Date("2010-05-18T00:00:00.000Z"), $lte: new Date("2010-05-18T23:59:59.999Z") } },
        { $unwind' : '$Statistics' },
        { $limit : 1 }
    ])

这个结果:

{ 
    "_id" : ObjectId("54a94200aa76d3db6cd51977"), 
    "URL" : "http://...", 
    "Statistics" : {
        "Date" : {
            "sec" : 1274166878,
            "usec" : 0
        },
        "Clicks" : 250
    }
}

由于性能原因,我不得不使用$group,不使用它不是一种选择。

正如我在PHP中所做的那样,我提到的文档、查询和结果中可能存在一些错误。希望这不会成为问题。我还没有弄清楚是什么导致了我的问题。有人能帮我吗?

编辑2:由于这似乎是一个无法解决的性能问题,我正在将"Statistics"数组中的所有数据迁移到自己的集合中。感谢任何人的帮助。

您需要运行$match两次,分别在之前和之后运行$unwind:

db.clicks.aggregate([
    { $match : { 'Statistics.Date' : { 
        $gte: new ISODate("2010-05-18T00:00:00.000Z"), 
        $lte: new ISODate("2010-05-18T23:59:59.999Z") } } },
    { $unwind: '$Statistics' },
    { $match : { 'Statistics.Date' : {
        $gte: new ISODate("2010-05-18T00:00:00.000Z"), 
        $lte: new ISODate("2010-05-18T23:59:59.999Z") } } },
    { $group : { 
        _id : { year : { $year : '$Statistics.Date' }, 
                month : { $month : '$Statistics.Date' }, 
                day : { $dayOfMonth : '$Statistics.Date' } },
        Clicks : { $sum : '$Statistics.Clicks' } } },
    { $sort : { _id : 1 } }
])

第一个$match用于选择在正确日期范围内具有至少一个Statistics元素的文档。第二个用于过滤掉那些文档中不在正确日期范围内的其他Statistics元素。

事情可能已经解决,但为寻求帮助的人发布答案

{ $match : 'Statistics.Date' : { $gte: new Date("2010-05-18T00:00:00.000Z"), 
enter code here$lte: new Date("2010-05-18T23:59:59.999Z") } }

此匹配将筛选主要文档。您想要的是过滤Statistics数组中的文档
现在,经过$match筛选的文档将包含完整的Statistics数组。过滤后展开可能会有Statistics的子文档,其同级文档(同一数组中的文档(已通过$match条件。

注:简单查找投影:db.col_name.find({},{"Statistics.$":1})也会过滤数组,但是聚合中的$project对筛选文档数组没有帮助。

相关内容

  • 没有找到相关文章

最新更新