简体   繁体   中英

MongoDB: Get the previous and next element in the embedded array

I have a database which has the following structure:

{
    "_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
        }
    ]
}

I've made the following query which will return the next 2 Elements form a Array after a specific TimeStamp.

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());
}

What I need are the documents befor and after this specific TimeStamp. Some kind of this:

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

But this doesn't work. How can I solve this problem? 2 separate queries are no option because of the duration.

You can try below aggregation query in 3.4.

The query will filter Move_events to keep events with timestamp less than input timestamp followed by $arrayElemAt to get the Move_events after and before event.

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"
                }
              ]
            }
          ]
        }
      }
    }
  }
])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM