Say I have the following two collections, sites
and webpages
. I'm trying to understand how to create an aggregation that'll allow me to combine values of a document from the sites
collection and use that to lookup a value from the webpages
collection. In addition, I need to prepend the combined values with a string.
// sites collection
[
{ "_id" : 3, "host" : "www.example-foo.com", "path": "/bar", "hasVisited": false },
]
// webpages collection
[
{ "_id" : 5, "url" : "https://www.example-foo.com/bar" },
{ "_id" : 8, "url" : "https://www.fizz.com/buzz" },
]
Without an aggregation I would do something like the following.
const site = await db.sites.findOne({ hasVisited: { $eq: false } });
const pages = await db.webpages.find({
url: `https://${site.host}${site.path}`, // <--- how to construct this in a lookup aggregation? string value value
});
// pages = [{ "_id" : 5, "url" : "https://www.example-foo.com/bar" }]
CodePudding user response:
This is like translation of your code with the 2 find queries in 1 using $lookup
Query
- first findOne is the
$match
and the$limit 1
$set
url is to make the string concat- second find is to do the
$lookup
(with the 1 site from above stages)
*if you want to do it for more than 1 sites remove the limit, and project more fields, to know where this pages belong to(which site)
db.sites.aggregate([
{
"$match": {
"hasVisited": {
"$eq": false
}
}
},
{
"$limit": 1
},
{
"$set": {
"url": {
"$concat": [
"https://",
"$host",
"$path"
]
}
}
},
{
"$lookup": {
"from": "webpages",
"localField": "url",
"foreignField": "url",
"as": "pages"
}
},
{
"$project": {
"_id": 0,
"pages": 1
}
}
])