从日期之间的子文档中获取数据

时间:2016-04-06 21:13:45

标签: mongodb

我正在尝试从我的文档中获取一定数量的历史数据,类似于SQL的Between子句。我搜索了类似的问题,并设法找到这个查询,但它只返回数组的第一个元素,所以这还不够:

db.docs.find({ _id: "eraj4983tj3" }, {history: { $elemMatch : {time: {$gt: new ISODate("2016-03-21T20:53:33.662Z") , $lt: new ISODate("2016-03-21T20:54:20.313Z") } } } });

我的文件如下:

{
    "_id": "eraj4983tj3",
    "descr": "somestuff",
    "history": [
        {
            "time": ISODate("2016-03-21T20:52:31.389Z"),
            "value": 103.91
        },
        {
            "time": ISODate("2016-03-21T20:53:33.663Z"),
            "value": 106.91
        },
        {
            "time": ISODate("2016-03-21T20:53:45.179Z"),
            "value": 104.91
        },
        {
            "time": ISODate("2016-03-21T20:54:20.313Z"),
            "value": 105.11
        },
        {
            "time": ISODate("2016-03-21T20:54:53.649Z"),
            "value": 105.41
        },
        {
            "time": ISODate("2016-03-21T20:55:12.998Z"),
            "value": 115.91
        }
    ]
}

我的查询结果应该返回:

{
    "_id": "eraj4983tj3",
    "history": [
        {
            "time": ISODate("2016-03-21T20:53:45.179Z"),
            "value": 104.91
        },
        {
            "time": ISODate("2016-03-21T20:54:20.313Z"),
            "value": 105.11
        },
        {
            "time": ISODate("2016-03-21T20:54:53.649Z"),
            "value": 105.41
        }
    ]
}

如何编写查询以实现此结果?

2 个答案:

答案 0 :(得分:3)

使用简单查询无法实现您的目标。但是,您可以使用聚合:

db.yourColl.aggregate([
    { $match:{ _id:"eraj4983tj3" } },
    { $unwind: "$history" },
    { $match:{ "history.time":{
        $gt: new ISODate("2016-03-21T20:53:33.662Z") ,
        $lt: new ISODate("2016-03-21T20:54:20.313Z")
    }}},
    { $group:{ _id:"$_id", history:{ $push:"$history" }}}
])

它为您提供

的(正确)结果
{
  "_id" : "eraj4983tj3",
  "history" : [
      { "time" : ISODate("2016-03-21T20:53:33.663Z"), "value" : 106.91 },
      { "time" : ISODate("2016-03-21T20:53:45.179Z"), "value" : 104.91 }
  ]
}

现在,让我们来看看各个阶段:

  1. { $match:{ _id:"eraj4983tj3" } } :找到正确的文档
  2. { $unwind: "$history" } 为每个数组项创建一个新文档,并将其发送到管道。 这个阶段的输出如下:

    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:52:31.389Z"), "value" : 103.91 } }
    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:53:33.663Z"), "value" : 106.91 } }
    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:53:45.179Z"), "value" : 104.91 } }
    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:54:20.313Z"), "value" : 105.11 } }
    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:54:53.649Z"), "value" : 105.41 } }
    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:55:12.998Z"), "value" : 115.91 } }
    
  3. { $match:{ "history.time":{ $gt: new ISODate("2016-03-21T20:53:33.662Z"), $lt: new ISODate("2016-03-21T20:54:20.313Z")}}} 我们再次匹配,以查找与我们的日期范围匹配的上一级的历史记录项。这个阶段的输出如下:

    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:53:33.663Z"), "value" : 106.91 } }
    { "_id" : "eraj4983tj3", "descr" : "somestuff", "history" : { "time" : ISODate("2016-03-21T20:53:45.179Z"), "value" : 104.91 } }
    
  4. { $group:{ _id:"$_id", history:{ $push:"$history" }}} 我们按_id分组(这里没有新内容),对于上一阶段输出的每个文档,我们 {{3在新创建的分组文档中,history(对象)到数组history的值。

答案 1 :(得分:1)

位置操作符$elemMatch只返回一个子文档。