MongoDB $lookup multiple localFields from one document - mongodb

I've got Adresses model:
{
user1: ObjectId(),
user2: ObjectId()
}
Each user field is reference to User model.
Is it possible to perform one lookup which will propagate data?

You can just put multiple references as following:
collection.aggregate([
{
$lookup: {
from: "whereyouwant",
localField: "localfield",
foreignField: "foreignfield",
as: "name1"
}
},
{
$lookup: {
from: "whereyouwant2",
localField: "localfield2",
foreignField: "foreignfield2",
as: "name2"
}
},... rest of code

Related

Adding a filter to Aggregate query in MongoDB

i'm trying to add a filter to my query in MongoDB to only return results after a certain date. I need to retrieve only dates from the transaction.CreatedAt column which are after the 11th Nov this year. I'm pretty new to MongoDB but really struggling to solve this. Any help would be awesome!
db.transactions.aggregate([
{
$lookup:
{
from: 'lessons',
localField: 'productId.id',
foreignField: '_id',
as: 'product'
}
},
{$unwind:'$product'},
{
$lookup:
{
from: 'schools',
localField: 'schoolId',
foreignField: '_id',
as: 'provider'
}
},
{$unwind:'$provider'},
{
$lookup:
{
from: 'users',
localField: 'userId',
foreignField: '_id',
as: 'user'
}
},
{$unwind:'$user'},
])
.projection({_id:1, createdAt:1, 'user.email':1})
.sort({_id:-1})
.limit(1500)
I tried to add the filter into the projection but couldn't get anything to run when I used $filter.
Tried below just using a $gte
projection({_id:1, createdAt:{ $gte: [ "createdAt", Date("2022-11-21T11:45:28+00:00")] }

MongoDB $lookup - conditional value for localfield?

I have 2 collections I want to combine using lookup.
Collection1: _AddressSyncStatus
fields I wanna use from this collection: "address"
Collection2: EthTokenTransfers
Fields I want to use from this collection: "to_address", "from_address".
Now when I use mongo compass, the lookup filter expects a local field, in my case the local field of EthTokenTransfers to join the collections. My problem now is, that I want to lookup where address from _AddressSyncStatus is either EthTokenTransfers.from_address OR EthTokenTransfers.to_address.
Is this possible using aggregations?
{
from: '_AddressSyncStatus',
localField: 'string', //from_address OR to_address
foreignField: 'address',
as: 'synced_address'
}
One way to do it is using the $lookup pipeline with $or:
db.EthTokenTransfers.aggregate([
{
$lookup: {
from: "_AddressSyncStatus",
let: {
from_address: "$from_address",
to_address: "$to_address"
},
pipeline: [
{
$match: {
$expr: {$or: [{$eq: ["$_id", "$$from_address"]},
{$eq: ["$_id", "$$to_address"]}
]
}
}
}
],
as: "synced_address"
}
}
])
As you can see here.
But I think that for the rset of the work with this data, it will be more convenient like this:
db.EthTokenTransfers.aggregate([
{
$lookup: {
from: "_AddressSyncStatus",
localField: "from_address",
foreignField: "_id",
as: "synced_address_from"
}
},
{
$lookup: {
from: "_AddressSyncStatus",
localField: "to_address",
foreignField: "_id",
as: "synced_address_to"
}
}
])
As you can see here

Aggregation based many collection

I have 3 tables like
Actor
actor_id: "1"
first_name: "Penelope"
last_name: "Guiness"
Films
film_id: "1"
title: "ABC"
Film_Actor
film_id: "1"
actor_id: "22"
I want to get movies (title) starring by an actor, like
actor_id: "1"
title: {"ABC", "DEF", "GHI"}
in this case I have not been able to get it, what I just achieved is only aggregation based on 2 collections like:
db.actor.aggregate ([
{
$ lookup:
{
from: 'film_actor',
localField: 'actor_id',
foreignField: 'actor_id',
as: 'film_id'
} }
])
First of all I think you have a data model issue there. It looks like a SQL database and that's not the idea of using mongo.
But if you want to do it anyway you should do:
db.actor.aggregate([
{
$lookup: {
from: "film_actor", // the collection you are trying to match
localField: "actor_id",
foreignField: "actor_id",
as: "film_actor"
}
},
{
$lookup: {
from: "films", // the collection you are trying to match
localField: "film_actor.film_id", // or '$film_actor.actor_id' if it does not work
foreignField: "film_id",
as: "film"
}
},
{
$group: {
_id: "$actor_id",
titles: {$push: "$film.title"}
}
}
]);
I hope you find it useful.

MongoDB Merge two properties from different collections into one and sort them

I'm faced into the issue when I'm trying to merge the results of two MongoDB lookup's into one property, and then I want to unwind them and sort.
I have a problem with merging the results of lookup's.
Here is the actual code:
db.getCollection('collectionA').aggregate([
{
$lookup:
{
from: 'collectionB',
localField: "_id",
foreignField: "collectionAKey",
as: "collectionBInfo"
}
},
{
$lookup:
{
from: 'collectionC',
localField: "_id",
foreignField: "collectionAKey",
as: "collectionCInfo"
}
},
/// then I just want to create one property from both of lookup's, unwind them and sort by the timestamp
{
$unwind: "$mergedCollectionsAandB"
},
{
$sort: {
"mergedCollectionsAandB.timestamp": -1
}
}
])
Here is a models of collections:
CollectionA
_id
name
CollectionB
_id
timestamp
collectionAKey
CollectionC
_id
timestamp
collectionAKey
I assume that it's possible by using $mergeObjects MongoDB operator, but I'm stuck a little bit how to do it in a right way. Is that possible? Thanks in advance.
So the final version of my query looks like that, it's what I was looking for:
db.getCollection('collectionA').aggregate([
{
$lookup:
{
from: 'collectionB',
localField: "_id",
foreignField: "collectionAKey",
as: "collectionBInfo"
}
},
{
$lookup:
{
from: 'collectionC',
localField: "_id",
foreignField: "collectionAKey",
as: "collectionCInfo"
}
},
{
$project: {
"mergedCollectionsAandB": { $concatArrays: ["$collectionBInfo", "$collectionCInfo"] }
}
},
{
$unwind: "$mergedCollectionsAandB"
},
{
$sort: {
"mergedCollectionsAandB.timestamp": -1
}
}
])

$lookup where id fields are of different types

I have 2 collections : Transactions & Accounts.
I need to join Accounts to Transactions so I can group on the Accounts.acctType field. The problem is that Transactions.accountId is of type 'string' and Accounts._id is of type 'Int32'.
is there any way to get around this problem without having to change the Transactions.accountId type?
Current lookup code:
$lookup: {
from: 'accounts',
localField: accountId,
foreignField: '_id',
as: 'accountData'
}
What I need:
$lookup: {
from: 'accounts',
localField: Number(accountId), //something like this
foreignField: '_id',
as: 'accountData'
}
Or:
$lookup: {
from: 'accounts',
localField: accountId,
foreignField: '_id.toString()', //or something like this
as: 'accountData'
}
You can $project your document and use $toLower to convert the "Transaction" "_id" field to string.
db.Transaction.aggregate(
[
{ "$project": { "_id": { "$toLower": "$_id" } } }, // You need include all the fields you want in your result.
{ "$lookup": {
"from": "accounts",
"localField": "accountId",
"foreignField": "_id",
"as": "accountData"
}}
]
)
I ended up making a database change to get the Id field inline with the data type.