I have two collections that are in many-to-one relationship (multiple hosts' http services often serve the 'same' e.g. DNS-level load balancing). I'm trying to build a query returning the relevant documents (from two collections) merged into one.
hosts collection:
{
"_id" : ObjectId("60aa2485332483cb4f5e7122"),
"ip" : "1.2.3.4",
"services" : [
{
"proto" : "tcp",
"port" : "22",
"status" : "open",
"reason" : "syn-ack",
"ttl" : 53,
},
{
"proto" : "tcp",
"port" : "80",
"status" : "open",
"reason" : "syn-ack",
"ttl" : 51,
"http" : [
ObjectId("60aa64c67d0bf23ce47c530c")
]
}
],
"version" : 4,
"last_scanned" : 1621573240.730579,
https collection:
{
"_id" : ObjectId("60aa64c67d0bf23ce47c530c"),
"vhost" : "test.com",
"paths" : [
{
"path" : "/admin",
"code" : 200
},
{
"path" : "/stuff",
"code" : 200
}
]
}
I'd like to write a lookup where the output is a combination of these two collections. So far I was able to get the https document into a top-level array in hosts:
db.hosts.aggregate([
{
$lookup:
{
from: "https",
localField: "services.http",
foreignField: "_id",
as: 'http'
}
}
]).pretty()
Which ends up as:
{
"_id" : ObjectId("60aa2485332483cb4f5e7122"),
"ip" : "1.2.3.4",
"services" : [
{
"proto" : "tcp",
"port" : "22",
"status" : "open",
"reason" : "syn-ack",
"ttl" : 53,
},
{
"proto" : "tcp",
"port" : "80",
"status" : "open",
"reason" : "syn-ack",
"ttl" : 51,
"http" : [
ObjectId("60aa64c67d0bf23ce47c530c")
]
}
],
"http" : [
{
"_id" : ObjectId("60aa64c67d0bf23ce47c530c"),
"vhost" : "test.com",
"paths" : [
{
"path" : "/admin",
"code" : 200
},
{
"path" : "/stuff",
"code" : 200
}
]
}
]
"version" : 4,
"last_scanned" : 1621573240.730579
]
}
The problem is that I can't move the "http" field to the place where it's ObjectId was found by lookup (services.$.http). I was trying to modify the 'as' field of $lookup in various ways without success.
Is it even possible to point to lower levels of a nested document with 'as'? Any workaround to achieve this?