Mongodb 聚合、匹配、分组和排序复杂 JSON
Mongodb aggregate, match, group and sort on complex JSON
我收到了大量 JSON 返回(航班数据),我一直在考虑使用 mongo 作为工具 query/filter 它,然后返回 UI.
这是jsonresponse from Sabre (flight search)
{
"OTA_AirLowFareSearchRS": {
"PricedItineraries": {
"PricedItinerary": [
{
"SequenceNumber": 1,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T11:40:00",
"ArrivalDateTime": "2015-11-12T17:35:00",
"FlightNumber": "1980"
},
{
"DepartureDateTime": "2015-11-12T19:35:00",
"ArrivalDateTime": "2015-11-13T02:00:00",
"FlightNumber": "760"
}
]
},
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T08:25:00",
"ArrivalDateTime": "2015-11-19T11:40:00",
"FlightNumber": "763"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56,
"CurrencyCode": "GBP"
}
}
}
]
},
{
"SequenceNumber": 2,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T16:45:00",
"ArrivalDateTime": "2015-11-12T22:40:00",
"FlightNumber": "1986"
},
{
"DepartureDateTime": "2015-11-13T00:40:00",
"ArrivalDateTime": "2015-11-13T07:10:00",
"FlightNumber": "762"
}
]
},
{
"ElapsedTime": 640,
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T08:25:00",
"ArrivalDateTime": "2015-11-19T11:40:00",
"FlightNumber": "763"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56,
"CurrencyCode": "GBP"
}
}
}
]
},
{
"SequenceNumber": 6,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T11:40:00",
"ArrivalDateTime": "2015-11-12T17:35:00",
"FlightNumber": "1980"
},
{
"DepartureDateTime": "2015-11-12T19:35:00",
"ArrivalDateTime": "2015-11-13T02:00:00",
"FlightNumber": "760"
}
]
},
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T03:15:00",
"ArrivalDateTime": "2015-11-19T06:30:00",
"FlightNumber": "761"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56
}
}
}
]
}
]
}
}
}
我一直在努力将它变成我想要的视图,但一直在努力应对所有嵌套数组的复杂性。我的问题是我怎样才能达到这样的预期结果:
{
'Price': 269.56, <-- //Group on price (TotalFare)
'Outbound': [{
<Outbound Flights> <--- //$push? flights at array position [0] of OriginDestinationOption
}],
'Inbound': [{
<Inbound Flights> <-- // flights at array position [1] of OriginDestinationOption
}]
},
...
这些数据在 JSON 中的位置是:
Price: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItineraryPricingInfo[0].ItinTotalFare.TotalFare.Amount;
Inbound: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItinerary.OriginDestinationOptions.OriginDestinationOption[0]
Outbound: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItinerary.OriginDestinationOptions.OriginDestinationOption[1]
在当前的 MongoDB 版本中,获得更接近您想要的结果的唯一方法是使用 aggregation framework, and working on the premise that the OriginDestinationOption
array will have two elememts, you'd need the $first
and $last
operators to select the first and last elements in the array after the $unwind
运算符。现在(基于上述假设)您可能需要处理 运行 这条管道:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"Outbound" : { "$first": "$DestinationOptions" },
"Inbound" : { "$last": "$DestinationOptions" }
}
}
])
这将产生结果(来自示例数据):
/* 1 */
{
"result" : [
{
"_id" : 269.56,
"Outbound" : {
"ElapsedTime" : 620,
"FlightSegment" : [
{
"DepartureDateTime" : "2015-11-12T11:40:00",
"ArrivalDateTime" : "2015-11-12T17:35:00",
"StopQuantity" : 0,
"FlightNumber" : "1980",
"ElapsedTime" : 235,
"DepartureAirport" : {
"LocationCode" : "LHR",
"TerminalID" : "2",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "1980",
"content" : ""
}
},
{
"DepartureDateTime" : "2015-11-12T19:35:00",
"ArrivalDateTime" : "2015-11-13T02:00:00",
"StopQuantity" : 0,
"FlightNumber" : "760",
"ResBookDesigCode" : "W",
"ElapsedTime" : 265,
"DepartureAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "DXB",
"TerminalID" : "1",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "760",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "343",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "I",
"DepartureTimeZone" : {
"GMTOffset" : 2
},
"ArrivalTimeZone" : {
"GMTOffset" : 4
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
}
]
},
"Inbound" : {
"ElapsedTime" : 730,
"FlightSegment" : [
{
"DepartureDateTime" : "2015-11-19T08:25:00",
"ArrivalDateTime" : "2015-11-19T11:40:00",
"StopQuantity" : 0,
"FlightNumber" : "763",
"ResBookDesigCode" : "W",
"ElapsedTime" : 315,
"DepartureAirport" : {
"LocationCode" : "DXB",
"TerminalID" : "1",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "763",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "330",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "O",
"DepartureTimeZone" : {
"GMTOffset" : 4
},
"ArrivalTimeZone" : {
"GMTOffset" : 2
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
},
{
"DepartureDateTime" : "2015-11-19T14:25:00",
"ArrivalDateTime" : "2015-11-19T16:35:00",
"StopQuantity" : 0,
"FlightNumber" : "1971",
"ResBookDesigCode" : "W",
"ElapsedTime" : 250,
"DepartureAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "LHR",
"TerminalID" : "2",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "1971",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "32B",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "I",
"DepartureTimeZone" : {
"GMTOffset" : 2
},
"ArrivalTimeZone" : {
"GMTOffset" : 0
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
}
]
}
}
],
"ok" : 1
}
但是,在未来的版本中 (MongoDB 3.2 and newer), there are two operators $slice
and $arrayElemAt
which will work for you to produce the desired result. The $slice
operator returns a subset of an array and the $arrayElemAt
returns 指定数组索引处的元素。
因此您将按如下方式实现管道 -
案例 1. 使用 $slice
运算符:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"DestinationOptions" : { "$push": "$DestinationOptions" }
}
},
{
"$project": {
"Inbound": { "$slice": [ "$DestinationOptions", 0, 1] },
"Outbound": { "$slice": [ "$DestinationOptions", 1, 1 ] },
"Price": "$_id",
"_id": 0
}
}
])
案例 2. 使用 $arrayElemAt
运算符:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"DestinationOptions" : { "$push": "$DestinationOptions" }
}
},
{
"$project": {
"Inbound": { "$arrayElemAt": [ "$DestinationOptions", 0] },
"Outbound": { "$arrayElemAt": [ "$DestinationOptions", 1 ] },
"Price": "$_id",
"_id": 0
}
}
])
我收到了大量 JSON 返回(航班数据),我一直在考虑使用 mongo 作为工具 query/filter 它,然后返回 UI.
这是jsonresponse from Sabre (flight search)
{
"OTA_AirLowFareSearchRS": {
"PricedItineraries": {
"PricedItinerary": [
{
"SequenceNumber": 1,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T11:40:00",
"ArrivalDateTime": "2015-11-12T17:35:00",
"FlightNumber": "1980"
},
{
"DepartureDateTime": "2015-11-12T19:35:00",
"ArrivalDateTime": "2015-11-13T02:00:00",
"FlightNumber": "760"
}
]
},
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T08:25:00",
"ArrivalDateTime": "2015-11-19T11:40:00",
"FlightNumber": "763"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56,
"CurrencyCode": "GBP"
}
}
}
]
},
{
"SequenceNumber": 2,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T16:45:00",
"ArrivalDateTime": "2015-11-12T22:40:00",
"FlightNumber": "1986"
},
{
"DepartureDateTime": "2015-11-13T00:40:00",
"ArrivalDateTime": "2015-11-13T07:10:00",
"FlightNumber": "762"
}
]
},
{
"ElapsedTime": 640,
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T08:25:00",
"ArrivalDateTime": "2015-11-19T11:40:00",
"FlightNumber": "763"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56,
"CurrencyCode": "GBP"
}
}
}
]
},
{
"SequenceNumber": 6,
"AirItinerary": {
"OriginDestinationOptions": {
"OriginDestinationOption": [
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-12T11:40:00",
"ArrivalDateTime": "2015-11-12T17:35:00",
"FlightNumber": "1980"
},
{
"DepartureDateTime": "2015-11-12T19:35:00",
"ArrivalDateTime": "2015-11-13T02:00:00",
"FlightNumber": "760"
}
]
},
{
"FlightSegment": [
{
"DepartureDateTime": "2015-11-19T03:15:00",
"ArrivalDateTime": "2015-11-19T06:30:00",
"FlightNumber": "761"
},
{
"DepartureDateTime": "2015-11-19T12:55:00",
"ArrivalDateTime": "2015-11-19T15:05:00",
"FlightNumber": "1985"
}
]
}
]
}
},
"AirItineraryPricingInfo": [
{
"ItinTotalFare": {
"TotalFare": {
"Amount": 269.56
}
}
}
]
}
]
}
}
}
我一直在努力将它变成我想要的视图,但一直在努力应对所有嵌套数组的复杂性。我的问题是我怎样才能达到这样的预期结果:
{
'Price': 269.56, <-- //Group on price (TotalFare)
'Outbound': [{
<Outbound Flights> <--- //$push? flights at array position [0] of OriginDestinationOption
}],
'Inbound': [{
<Inbound Flights> <-- // flights at array position [1] of OriginDestinationOption
}]
},
...
这些数据在 JSON 中的位置是:
Price: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItineraryPricingInfo[0].ItinTotalFare.TotalFare.Amount;
Inbound: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItinerary.OriginDestinationOptions.OriginDestinationOption[0]
Outbound: OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary[x].AirItinerary.OriginDestinationOptions.OriginDestinationOption[1]
在当前的 MongoDB 版本中,获得更接近您想要的结果的唯一方法是使用 aggregation framework, and working on the premise that the OriginDestinationOption
array will have two elememts, you'd need the $first
and $last
operators to select the first and last elements in the array after the $unwind
运算符。现在(基于上述假设)您可能需要处理 运行 这条管道:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"Outbound" : { "$first": "$DestinationOptions" },
"Inbound" : { "$last": "$DestinationOptions" }
}
}
])
这将产生结果(来自示例数据):
/* 1 */
{
"result" : [
{
"_id" : 269.56,
"Outbound" : {
"ElapsedTime" : 620,
"FlightSegment" : [
{
"DepartureDateTime" : "2015-11-12T11:40:00",
"ArrivalDateTime" : "2015-11-12T17:35:00",
"StopQuantity" : 0,
"FlightNumber" : "1980",
"ElapsedTime" : 235,
"DepartureAirport" : {
"LocationCode" : "LHR",
"TerminalID" : "2",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "1980",
"content" : ""
}
},
{
"DepartureDateTime" : "2015-11-12T19:35:00",
"ArrivalDateTime" : "2015-11-13T02:00:00",
"StopQuantity" : 0,
"FlightNumber" : "760",
"ResBookDesigCode" : "W",
"ElapsedTime" : 265,
"DepartureAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "DXB",
"TerminalID" : "1",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "760",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "343",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "I",
"DepartureTimeZone" : {
"GMTOffset" : 2
},
"ArrivalTimeZone" : {
"GMTOffset" : 4
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
}
]
},
"Inbound" : {
"ElapsedTime" : 730,
"FlightSegment" : [
{
"DepartureDateTime" : "2015-11-19T08:25:00",
"ArrivalDateTime" : "2015-11-19T11:40:00",
"StopQuantity" : 0,
"FlightNumber" : "763",
"ResBookDesigCode" : "W",
"ElapsedTime" : 315,
"DepartureAirport" : {
"LocationCode" : "DXB",
"TerminalID" : "1",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "763",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "330",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "O",
"DepartureTimeZone" : {
"GMTOffset" : 4
},
"ArrivalTimeZone" : {
"GMTOffset" : 2
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
},
{
"DepartureDateTime" : "2015-11-19T14:25:00",
"ArrivalDateTime" : "2015-11-19T16:35:00",
"StopQuantity" : 0,
"FlightNumber" : "1971",
"ResBookDesigCode" : "W",
"ElapsedTime" : 250,
"DepartureAirport" : {
"LocationCode" : "IST",
"TerminalID" : "I",
"content" : ""
},
"ArrivalAirport" : {
"LocationCode" : "LHR",
"TerminalID" : "2",
"content" : ""
},
"OperatingAirline" : {
"Code" : "TK",
"FlightNumber" : "1971",
"content" : ""
},
"Equipment" : [
{
"AirEquipType" : "32B",
"content" : ""
}
],
"MarketingAirline" : {
"Code" : "TK",
"content" : ""
},
"MarriageGrp" : "I",
"DepartureTimeZone" : {
"GMTOffset" : 2
},
"ArrivalTimeZone" : {
"GMTOffset" : 0
},
"TPA_Extensions" : {
"eTicket" : {
"Ind" : true
}
}
}
]
}
}
],
"ok" : 1
}
但是,在未来的版本中 (MongoDB 3.2 and newer), there are two operators $slice
and $arrayElemAt
which will work for you to produce the desired result. The $slice
operator returns a subset of an array and the $arrayElemAt
returns 指定数组索引处的元素。
因此您将按如下方式实现管道 -
案例 1. 使用 $slice
运算符:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"DestinationOptions" : { "$push": "$DestinationOptions" }
}
},
{
"$project": {
"Inbound": { "$slice": [ "$DestinationOptions", 0, 1] },
"Outbound": { "$slice": [ "$DestinationOptions", 1, 1 ] },
"Price": "$_id",
"_id": 0
}
}
])
案例 2. 使用 $arrayElemAt
运算符:
db.flights.aggregate([
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo" },
{ "$unwind": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption" },
{
"$project": {
"Price": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItineraryPricingInfo.ItinTotalFare.TotalFare.Amount",
"DestinationOptions": "$OTA_AirLowFareSearchRS.PricedItineraries.PricedItinerary.AirItinerary.OriginDestinationOptions.OriginDestinationOption"
}
},
{
"$group": {
"_id": "$Price",
"DestinationOptions" : { "$push": "$DestinationOptions" }
}
},
{
"$project": {
"Inbound": { "$arrayElemAt": [ "$DestinationOptions", 0] },
"Outbound": { "$arrayElemAt": [ "$DestinationOptions", 1 ] },
"Price": "$_id",
"_id": 0
}
}
])