#mongodb #aggregate
Вопрос:
У меня есть оператор OR, в котором ожидаемый результат должен возвращать 2 документа, но возвращаемый результат-только 1 документ. У меня есть список документов по автомобилям:
[
{
"_id": ObjectId("60a2c0621e5f043b735e36ef"),
"car_id": 78,
"terminal": "JFK",
"timestamp": ISODate("2020-01-01T17:00:00.000Z"),
},
{
"_id": ObjectId("60a2c0621e5f043b735e36f0"),
"car_id": 78,
"terminal": "LAX",
"timestamp": ISODate("2020-02-08T17:00:00.000Z"),
},
{
"_id": ObjectId("60a2c0621e5f043b735e36f1"),
"car_id": 78,
"terminal": "ORD",
"timestamp": ISODate("2020-03-01T17:00:00.000Z"),
},
]
и мой запрос запрашивает 2 экземпляра с ОДИНАКОВЫМ идентификатором АВТОМОБИЛЯ, но с РАЗНОЙ отметкой времени:
db.collection.aggregate([
{
"$match": {
"$or": [
{
"car_id": 78,
"timestamp": {
"$lte": ISODate("2020-02-15T05:00:11.000Z")
}
},
{
"car_id": 78,
"timestamp": {
"$lte": ISODate("2020-03-02T11:07:27.000Z")
}
}
]
}
},
{
"$sort": {
"timestamp": 1
}
},
{
"$group": {
"_id": "$car_id",
"last": {
"$last": "$ROOT"
}
}
}
])
Поэтому я ожидаю получить 2 результата (для каждого запроса).
Ожидаемый результат:
[
{
"_id": 78,
"last": {
"_id": ObjectId("60a2c0621e5f043b735e36f1"),
"car_id": 78,
"terminal": "ORD",
"timestamp": ISODate("2020-03-01T17:00:00Z")
}
},
{
"_id": 78,
"last": {
"_id": ObjectId("60a2c0621e5f043b735e36f0"),
"car_id": 78,
"terminal": "LAX",
"timestamp": ISODate("2020-02-08T17:00:00Z")
}
}
]
Но я получаю только первый результат. Как я могу получить желаемые 2 результата?
Комментарии:
1. Уважаемый ПроколХарум, рекомендуется, чтобы вопрос содержал всю необходимую информацию в самом вопросе. Хотя mongoplayground-удивительный сервис и очень помогает, не было очевидно, что вы также группируете результаты.
2. @AlexBlex хорошо понял. Я вижу, что вы его добавили. Спасибо
Ответ №1:
Потому что все возвращенные документы одинаковы car_id
, и вы используете car_id
их на $group
этапе, поэтому они будут сгруппированы в один результат. Чтобы получить ожидаемый результат, вы можете добавить поле в зависимости от метки времени документа, а затем использовать его в $group
:
db.collection.aggregate([
{
"$match": {
"$or": [
{
"car_id": 78,
"timestamp": {
"$lte": ISODate("2020-02-15T05:00:11.000Z")
}
},
{
"car_id": 78,
"timestamp": {
"$lte": ISODate("2020-03-02T11:07:27.000Z")
}
}
]
}
},
{
"$sort": {
"timestamp": 1
}
},
{
$addFields: {
group: {
$cond: {
if: {
$lte: [
"$timestamp",
ISODate("2020-02-15T05:00:11.000Z")
]
},
then: 1,
else: 2
}
}
}
},
{
"$group": {
"_id": "$group",
"last": {
"$last": "$ROOT"
}
}
}
])
Примечание: Если в результате у вас более одного car_id
, вы можете изменить значение $group
на:
{
"$group": {
"_id": {
car_id: "$car_id",
group: "$group",
},
"last": {
"$last": "$ROOT"
}
}
}