so my goal is when i make a requests to the database, check if theres no data returned from the database.
Can you help me? Thanks!
Heres my code:
let rqs: any = this.friendrequestModel
.aggregate([
{
$lookup: {
from: "users",
localField: "author",
foreignField: "_id",
as: "userdata",
// pipeline: [
// {
// $match: {
// friend_id: new mongoose.Types.ObjectId(userid)
// }
// }
// ],
},
},
])
.exec((err, data) => {
if (err) {
console.log(err);
}
if(!data){
console.log("No data returned")
}
});
Related
I have two collections in my mongoDb database, one called media, one called users.
Documents in the media collection:
{"_id":{"$oid":"6379204a8cf5677554c26c1b"},"_partition":"6378eb74f6613d5d4192da79","name":"silas test"}
{"_id":{"$oid":"6378eb74f6613d5d4192da79"},"_partition":"6378eb74f6613d5d4192da79","name":"test media"}
Document in the users collection:
{
"_id":{
"$oid":"6379ee6c770a8f43afc8e3e4"},
"_partition":"6378eb74f6613d5d4192da79",
"types":[
{
"mediaReference":[
{"$oid":"6379204a8cf5677554c26c1b"}
],
"mediatype":"podcast"
},
{
"mediaReference":[
{"$oid":"6378eb74f6613d5d4192da79"}
],
"mediatype":"movie"
}
],
"username":"silas"
}
Now im looking for a way to use the mongoDb aggregation pipeline to get the following result:
{
"_id":{
"$oid":"6379ee6c770a8f43afc8e3e4"},
"_partition":"6378eb74f6613d5d4192da79",
"types":[
{
"mediaReference":[
{
"_id": {
"$oid":"6379204a8cf5677554c26c1b"
},
"_partition":"6378eb74f6613d5d4192da79",
"name":"silas test"
}
],
"mediatype":"podcast"
},
{
"mediaReference":[
{
"_id": {
"$oid":"6378eb74f6613d5d4192da79"
},
"_partition":"6378eb74f6613d5d4192da79",
"name":"test media"
}
],
"mediatype":"movie"
}
],
"username":"silas"
}
Basically im searching for a way to paste the refferenced document into the mediaReference object inside the users document.
i would appreciate any help
EDIT:
I've found the solution:
db.users.aggregate([{
$unwind: {
path: '$types'
}
}, {
$lookup: {
from: 'media',
localField: 'types.mediaReference',
foreignField: '_id',
as: 'types.mediaReference'
}
}, {
$group: {
_id: '$_id',
merged: {
$first: '$$ROOT'
},
types: {
$push: '$types'
}
}
}, {
$addFields: {
'merged.types': '$types'
}
}, {
$replaceRoot: {
newRoot: '$merged'
}
}])
I am trying to connect two tables using aggregate in MongoDB and Deno using this library:
https://deno.land/x/mongo#v0.20.1
According to documentation, this is how we can use it.
// aggregation
const docs = await users.aggregate([
{ $match: { username: "many" } },
{ $group: { _id: "$username", total: { $sum: 1 } } },
]);
But there is no facility or scope to connect two different tables using $lookup and $project
Is there any other way to use lookup and project together in Deno?
This is how aggregation works in Deno and deno_mongo.
var data = Report.aggregate([
{
$lookup: {
from: "users",
localField: "senderId",
foreignField: "_id",
as: "sender",
},
},
{
$lookup: {
from: "users",
localField: "reportedId",
foreignField: "_id",
as: "reported",
},
},
{ $match: { status : 1 } },
{ $sort: { createdAt: 1} },
{ $skip: 10 },
{ $limit: 5 },
]).toArray();
I have collections like this:
// tasks
[
{_id: '123', _user: '345', _solutions: ['567', '678'] }
]
// solutions
[
{ _id: '567', _task: '123', _user: '345' },
{ _id: '678', _task: '123', _user: '345' }
]
// users
[
{ _id: '345', name: 'Tom' }
]
With this code:
await db
.collection<Task>('tasks')
.aggregate([
{ $match: { _id: id } },
{
$lookup: {
from: 'solutions',
// I guess here should be pipeline
localField: '_solutions',
foreignField: '_id',
as: '_solutions',
},
},
{ $lookup: { from: 'users', localField: '_user', foreignField: '_id', as: '_user' } },
])
I have result as below:
task = {
_id: 5e14e877fa42402079e38e44,
_solutions: [
{
_id: 5e15022ccafcb4869c153e61,
_task: 5e14e877fa42402079e38e44,
_user: 5e007403fd4ca4f47df69913, <-- this should be userObject instead
},
{
_id: 5e164f31cafcb4869c153e62,
_task: 5e14e877fa42402079e38e44,
_user: 5e007403fd4ca4f47df69913, <-- this should be userObject instead
}
],
_user: [
{
_id: 5e007403fd4ca4f47df69913,
_solutions: [Array],
_tasks: [Array],
}
]
}
and I don't know how to $lookup into _solutions._user - so instead of objectId I will have exact user object.
You can run $lookup with custom pipeline for outer lookup and the regular one for users:
db.tasks.aggregate([
{
$match: {
_id: "123"
}
},
{
$lookup: {
from: "solutions",
let: { solutions: "$_solutions" },
pipeline: [
{ $match: { $expr: { $in: [ "$_id", "$$solutions" ] } } },
{
$lookup: {
from: "users",
localField: "_user",
foreignField: "_id",
as: "_user"
}
},
{ $unwind: "$_user" }
],
as: "_solutions",
}
}
])
Mongo Playground
I have seen a ton of question about the $lookup aggregator for arrays of ObjectIds but I can't seem to find anything about when the ObjectId is inside an array of embedded documents.
I have the follow document inside a mongodb database:
_id: ObjectId('...')
Alarms: [
{
Gateway: ObjectId('...')
Port: 1
},
{
Gateway: ObjectId('...')
Port: 2
}
]
I would like to have the following:
_id: ObjectId('...')
Alarms [
{
Gateway: ...(Gateway Object),
Port: 1
},
{
Gateway: ...(Gateway Object),
Port: 2
}
]
I have tried the following with no success:
$lookup: {
from: 'Gateway',
localField: 'Alarms.Gateway',
foreignField: '_id',
as: 'Alarms.Gateway'
}
But this gives me the following result:
_id: ObjectId('...')
Alarms [
{
Gateway: {
...(Gateway Object)
}
Port: 1
}
]
Please try the below queries :
If you don't want the object which doesn't have match in Gateway collection exist in Alarms array in final result :
db.Alarms.aggregate([{ $unwind: '$Alarms' }, {
$lookup: {
from: 'Gateway',
localField: 'Alarms.Gateway',
foreignField: '_id',
as: 'Alarms.Gateway'
}
}, { $match: { 'Alarms.Gateway': { $ne: [] } } },
{ $addFields: { 'Alarms.Gateway': { $arrayElemAt: ['$Alarms.Gateway', 0] } } },
{ $group: { _id: '$_id', Alarms: { $push: '$Alarms' } } }
])
Test : MongoDB-Playground
Otherwise, if you want all objects in Alarms array to be returned irrespective of whether there is a match in Gateway or not :
db.Alarms.aggregate([{ $unwind: '$Alarms' }, {
$lookup: {
from: 'Gateway',
localField: 'Alarms.Gateway',
foreignField: '_id',
as: 'Alarms.GatewayObj'
}
}, { $addFields: { 'Alarms.Gateway': { $cond: [{ $ne: ['$Alarms.GatewayObj', []] }, { $arrayElemAt: ['$Alarms.GatewayObj', 0] }, '$Alarms.Gateway'] } } },
{ $project: { 'Alarms.GatewayObj': 0 } },
{ $group: { _id: '$_id', Alarms: { $push: '$Alarms' } } }
])
Test : MongoDB-Playground
Difference between two queries would be one will return below object in Alarms array (Vs) one don't.
{
"Gateway": ObjectId("5e2b5425d02e05b6940de2fb"),
"Port": 2
}
The idea here is to return an array of documents of the users' followers with the information if this user is a friend of that follower or not.
So far I have:
db.getCollection('users').aggregate([
{ $match: { _id: ObjectId("588877d82523b4395039910a") } },
{ $lookup: {
from: 'users',
localField: 'followers',
foreignField: '_id',
as: 's_followers'
}
},
{
$project: {
"s_followers._id": 1,
"s_followers.isFriend": {
$in: ["s_followers.id",
{ $setIntersection: ["$friends", "$followers"] }
]}
}
}
])
But the "s_followers.id" used in the $in operator doesn't seem to retrieve the _id information from the follower, so it always returns false.
When I use a ObjectId directly, I got the result I want:
"s_followers.isFriend": {
$in: [ObjectId("588877d82523b4395039910a"),
{ $setIntersection: ["$friends", "$followers"] }
]}
But I really need this ID to be a reference to the follower _id.
Expected result would be something like:
{
"_id" : ObjectId("588877d82523b4395039910a"),
"s_followers" : [
{
"_id" : ObjectId("5888687e56be8f172844d96f"),
"isFriend" : true
},
{
"_id" : ObjectId("5888ca27d79b8b03949a6e8c"),
"isFriend" : false
}
]
}
Thanks for your help!
UPD: A different approach (maybe easier), would be to use the ID of the user that I have (the one used on $match), but I would still need to get the reference for the follower's follower array
db.getCollection('users').aggregate([
{ $match: { _id: ObjectId("588877d82523b4395039910a") } },
{ $lookup: {
from: 'users',
localField: 'followers',
foreignField: '_id',
as: 's_followers'
}
}, {
$project: {
"firstName": 1,
"s_followers._id": 1,
"s_followers.firstName": 1,
"s_followers.followers": 1,
"s_followers.isFriend": { $in: [ObjectId("588877d82523b4395039910a"), "$s_followers.followers"] }
}
}
])
UPD2: The user data structure (the part that matters)
{
followers: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
friends: [{ type: mongoose.Schema.Types.ObjectId, ref: "User" }],
}
FOR VERSION 3.4.0+
Ok, just got it, I'll post here the code and my understanding of it:
db.getCollection('users').aggregate([
{ $match: { _id: ObjectId("588877d82523b4395039910a") } },
{ $lookup: {
from: 'users',
localField: 'followers',
foreignField: '_id',
as: 's_followers'
}
}, {
$project: {
"firstName": 1,
"s_followers._id": 1,
"s_followers.firstName": 1,
"s_followers.followers": 1,
}
}, {
$unwind: "$s_followers"
}, {
$project: {
"firstName": "$s_followers.firstName",
"isFriend": { $in: [ObjectId("588877d82523b4395039910a"), "$s_followers.followers"] }
}
}
])
My understanding of it:
$match: match the user I'm intended to get the followers of.
$lookup: found each follower detail
$project: select the information I want to return, also get the follower list of each follower
$unwind: create a different document for each follower
With the array unwinded, I can refer to the follower's followers array, and find my object id in it :)
In my example use followers friends list to check current user is friend or not. as {$arrayElemAt:["$s_followers.friends",0]} if want to find in followers then can use "$s_followers.followers"
You can try it.
db.getCollection('user').aggregate([
{ $match: { _id: ObjectId("5714d190e6128b7e7f8d9008") } },
{$unwind:"$followers"},
{ $lookup: {
from: 'user',
localField: 'followers',
foreignField: '_id',
as: 's_followers'
}
},
{$project:{
firstName:1,
s_followers:{$arrayElemAt:["$s_followers",0]},
isFriend:{$cond:[{
$anyElementTrue:{
$map: {"input": {$arrayElemAt:["$s_followers.friends",0]},
"as": "el",
"in": { "$eq": [ "$$el", "$_id" ] }
}
}
},true,false]}
}
},
{$group:{
_id:"$_id",
s_followers:{$push:{_id:"$s_followers._id",isFriend:"$isFriend"}}
}
}
])