MongoDB:获取嵌入式数组中的上一个和下一个元素

时间:2017-09-26 08:13:04

标签: mongodb aggregation-framework slice

我有一个具有以下结构的数据库:

{
    "_id" : ObjectId("59b8d72ab515211f3c161c4b"),
    "Transport_event_id" : 1,
    "Carrier_id" : 23,
    "Payload_id" : 0,
    "StartTime" : 214392.0,
    "EndTime" : 362707.0,
    "Move_events" : [ 
        {
            "Timestamp" : 214398,
            "x_pos" : 13,
            "y_pos" : 202
        },{
            "Timestamp" : 214845,
            "x_pos" : 12,
            "y_pos" : 202
        },{
            "Timestamp" : 216399,
            "x_pos" : 12,
            "y_pos" : 216
        },{
            "Timestamp" : 216842,
            "x_pos" : 11,
            "y_pos" : 216
        },{
            "Timestamp" : 219586,
            "x_pos" : 10,
            "y_pos" : 216
        }
    ]
}

我做了以下查询,它将在特定TimeStamp之后返回接下来的2个元素形成数组

var cursor = db.Transport_eventBeta.aggregate([
    { "$match": { "StartTime": { "$lte": query_time } } },
    { "$match": { "EndTime": { "$gte": query_time } } },
    {
        "$project": {
            "Move_events": {
                "$let": {
                    "vars": {
                        "filtered": {
                            "$filter": {
                                "input": "$Move_events",
                                "as": "event",
                                "cond": { "$lte": ["$$event.Timestamp" , query_time] }
                            }
                        }
                    },
                    "in": { 
                        "$slice": [
                            "$Move_events",
                            {"$size": "$$filtered"},
                            2
                        ]
                    }  
                }
            },
            "Carrier_id": 1    
        }
    }
])
while (cursor.hasNext()) {
   print(cursor.next());
}

我需要的是 befor和之后这个特定TimeStamp的文档。 某种形式:

"$slice": [
    "$Move_events",
    {"$size": "$$filtered"} - 1,
    2
]

但这不起作用。我怎么解决这个问题?由于持续时间的原因,2个单独的查询是无选择的。

1 个答案:

答案 0 :(得分:1)

您可以在3.4中尝试以下聚合查询。

该查询将过滤Move_events以保持时间戳小于输入timestamp的事件,然后$arrayElemAt以获取事件之前和之后的Move_events

db.Transport_eventBeta.aggregatee([
  {
    "$match": {
      "StartTime": {
        "$lte": query_time
      },
      "EndTime": {
        "$gte": query_time
      }
    }
  },
  {
    "$project": {
      "Move_events": {
        "$let": {
          "vars": {
            "filtered": {
              "$filter": {
                "input": "$Move_events",
                "as": "event",
                "cond": {
                  "$lte": [
                    "$$event.Timestamp",
                    query_time
                  ]
                }
              }
            }
          },
          "in": [
            {
              "$arrayElemAt": [
                "$Move_events",
                {
                  "$subtract": [
                    {
                      "$size": "$$filtered"
                    },
                    1
                  ]
                }
              ]
            },
            {
              "$arrayElemAt": [
                "$Move_events",
                {
                  "$size": "$$filtered"
                }
              ]
            }
          ]
        }
      }
    }
  }
])