У меня есть эти три коллекции, и я пытаюсь полностью заполнить поле messages
коллекции messages_lists
путем «объединения» данных из двух других коллекций.
1. списки сообщений:
{
"_id" : ObjectId("5e96207ea4143b3204373534"),
"name" : "6bq32q8TcP",
"messages" : [
{
"inserted" : ISODate("2020-04-14T20:43:42.086+0000"),
"srcId" : "DNWLMSNW217480-20200414T194933Z"
},
{
"inserted" : ISODate("2020-04-16T17:40:22.585+0000"),
"srcId" : "DNWLMSNW217737-20200416T163914Z"
}
]
}
2. сообщения:
{
"_id" : ObjectId("5e9615205bbcbe360ad40fb7"),
"srcId" : "DNWLMSNW217480-20200414T194933Z",
"status" : "expired",
"versions" : [
{
"direction" : NumberInt(-1),
"points" : [ 50080.028, 50080.029 ]
},
{
"direction" : NumberInt(1),
"points" : [ 50080.028, 50080.029 ]
}
]
},
{
"_id" : ObjectId("5e988b95ab20413033dbe9fb"),
"status" : "expired",
"srcId" : "DNWLMSNW217737-20200416T163914Z",
"versions" : [
{
"direction" : NumberInt(1),
"points" : [ 50060.096, 50060.097 ]
},
{
"direction" : NumberInt(-1),
"points" : [ 50060.096, 50060.097 ]
}
]
}
3. loc_points:
{
"locId" : 50060.096,
"road" : "A1",
"locCity" : NumberInt(445),
"locState" : NumberInt(260)
},
{
"locId" : 50060.097,
"road" : "A1",
"locCity" : NumberInt(445),
"locState" : NumberInt(260)
},
{
"locId" : 50080.028,
"road" : "A2",
"locCity" : NumberInt(690),
"locState" : NumberInt(260)
},
{
"locId" : 50080.029,
"road" : "A2",
"locCity" : NumberInt(690),
"locState" : NumberInt(260),
}
Моя версия mongoDB - 3.4.4, и это моя попытка решить проблему:
Шаг 1: Я смог успешно завершите первую стадию $ lookup с этим запросом:
db.getCollection("message_lists").aggregate([
{ $match: { name: '6bq32q8TcP' } },
{ $unwind: { path: '$messages', preserveNullAndEmptyArrays: true }},
{ $lookup: {
from: 'messages',
localField: 'messages.srcId',
foreignField: 'srcId',
as: 'messages'
}},
{ $unwind: { path: '$messages', preserveNullAndEmptyArrays: true }},
{ $group: {
_id: null,
messages: { $push: '$messages' }
}},
])
Я полностью удовлетворен результатом, который я получаю от вышеуказанного запроса. Выглядит это так, и в основном удалось заменить ссылку messages.srcId
на коллекцию messages
в исходной коллекции messages_list
полными данными сообщений, содержащимися в коллекции messages
:
{
"_id" : null,
"messages" : [
{
"_id" : ObjectId("5e9615205bbcbe360ad40fb7"),
"srcId" : "DNWLMSNW217480-20200414T194933Z",
"status" : "expired",
"versions" : [
{
"direction" : NumberInt(-1),
"points" : [ 50080.028, 50080.029 ]
},
{
"direction" : NumberInt(1),
"points" : [ 50080.028, 50080.029 ]
}
]
},
{
"_id" : ObjectId("5e988b95ab20413033dbe9fb"),
"srcId" : "DNWLMSNW217737-20200416T163914Z",
"status" : "expired",
"versions" : [
{
"direction" : NumberInt(1),
"points" : [ 50060.096, 50060.097 ]
},
{
"direction" : NumberInt(-1),
"points" : [ 50060.096, 50060.097 ]
}
]
}
]
}
Шаг 2: Цель этого шага - заполнить массивы messages.versions.points
данными из коллекции loc_points
, чтобы получить конечный результат, который должен выглядеть следующим образом:
Это то, что мне нужно, чтобы результат выглядел как :
{
"_id" : null,
"messages" : [
{
"_id" : ObjectId("5e9615205bbcbe360ad40fb7"),
"srcId" : "DNWLMSNW217480-20200414T194933Z",
"status" : "expired",
"versions" : [
{
"direction" : NumberInt(-1),
"points" : [
{
"locId" : 50080.028,
"road" : "A2",
"locCity" : NumberInt(690),
"locState" : NumberInt(260)
},
{
"locId" : 50080.029,
"road" : "A2",
"locCity" : NumberInt(690),
"locState" : NumberInt(260),
}
]
},
{
"direction" : NumberInt(1),
"points" : [
{
"locId" : 50080.028,
"road" : "A2",
"locCity" : NumberInt(690),
"locState" : NumberInt(260)
},
{
"locId" : 50080.029,
"road" : "A2",
"locCity" : NumberInt(690),
"locState" : NumberInt(260),
}
]
}
]
},
{
"_id" : ObjectId("5e988b95ab20413033dbe9fb"),
"srcId" : "DNWLMSNW217737-20200416T163914Z",
"status" : "expired",
"versions" : [
{
"direction" : NumberInt(1),
"points" : [
{
"locId" : 50060.096,
"road" : "A1",
"locCity" : NumberInt(445),
"locState" : NumberInt(260)
},
{
"locId" : 50060.097,
"road" : "A1",
"locCity" : NumberInt(445),
"locState" : NumberInt(260)
}
]
},
{
"direction" : NumberInt(-1),
"points" : [
{
"locId" : 50060.096,
"road" : "A1",
"locCity" : NumberInt(445),
"locState" : NumberInt(260)
},
{
"locId" : 50060.097,
"road" : "A1",
"locCity" : NumberInt(445),
"locState" : NumberInt(260)
}
]
}
]
}
]
}
Чтобы понять, мне нужно выполнить дополнительный поиск в $, например:
{ $lookup: {
from: 'loc_points',
localField: 'messages.versions.points',
foreignField: 'locId',
as: 'messages.versions.points',
}},
{ $unwind: { path: '$messages.versions.points', preserveNullAndEmptyArrays: true }}
Однако, после целого дня исследований и прочтения по крайней мере пяти других потоков stackoverflow, я не смог найти решение, напоминающее мою глубоко вложенную структуру документа.
Я был бы очень благодарен если кто-то, кто более знаком с платформой агрегации mongoDB, мог бы помочь мне здесь! Заранее спасибо !!
Редактировать: После того, как Джо посоветовался ниже, я добавил второй поиск $ перед заключительным оператором $ group. Итак, теперь мой общий запрос выглядит так:
db.getCollection("message_lists").aggregate([
{ $match: { name: '6bq32q8TcP' } },
{ $unwind: { path: '$messages', preserveNullAndEmptyArrays: true }},
{ $lookup: {
from: 'messages',
localField: 'messages.srcId',
foreignField: 'srcId',
as: 'messages'
}},
{ $unwind: { path: '$messages', preserveNullAndEmptyArrays: true }},
{ $lookup: {
from: 'loc_points',
localField: 'messages.versions.points',
foreignField: 'locId',
as: 'messages.versions.points',
}},
{ $group: {
_id: null,
messages: { $push: '$messages' }
}}
])
Однако в результате messages.versions.points
возвращается как пустой массив, все остальные поля version
отсутствуют, а messages.versions
даже не является массив больше:
{
"_id" : null,
"messages" : [
{
"_id" : ObjectId("5e9615205bbcbe360ad40fb7"),
"srcId" : "DNWLMSNW217480-20200414T194933Z",
"status" : "expired",
"versions" : {
"points" : [
]
},
},
{
"_id" : ObjectId("5e988b95ab20413033dbe9fb"),
"srcId" : "DNWLMSNW217737-20200416T163914Z",
"status" : "expired",
"versions" : {
"points" : [
]
},
}
]
}
Я просто не могу понять, как мне нужно изменить оператор $ group, чтобы правильно заполнить messages.versions.points
. Любая помощь приветствуется! (Я знаю, что из мира MySQL я показываю, что еще не полностью осознал концепцию агрегации, но в то же время я изо всех сил пытаюсь найти учебник, который соответствует моему сценарию)