Aggregate (Reflexive Join) in MongoDB - mongodb

I have the following data in collection "sampleorgchart":
Eventually we want to use the "Relationship" field in a match/filter statement, but first I just want to get some demo query to work with the hierarchy.
I am trying the following:
db.sampleorgchart2.aggregate([
{
$graphLookup: {
from: "sampleorgchart2",
startWith: "$To",
connectFromField: "To",
connectToField: "From",
as: "myList",
maxDepth: 2,
depthField: "depth"
}
}
])
It runs, but return 0 items in each of the "myList" fields:
// 1
{
"_id": ObjectId("6180023c68600000010000f5"),
"From": "John Doe",
"Relationship": "is CEO of ",
"To ": "Sample Company",
"myList": [ ]
}
Is something wrong with my query? I would like to see the connected rows in "myList".
For further practice, I copied the employee data from this page, and got that query working.
https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/#examples
So by changing the collection name and the field names, I don't understand why it won't work with my sampleorgchart2 collection. I got the query that page working, then reversed it to go down the hierarchy instead of up the hierarchy:
db.simpleorgchart.aggregate([
{
$graphLookup: {
from: "simpleorgchart",
startWith: "$reportsTo",
connectFromField: "name",
connectToField: "reportsTo",
as: "myReportingHierarchy",
maxDepth: 2,
depthField: "depth"
}
}
])
Sample results:
// 1
{
"_id": "1",
"name": "Dev",
"reportsTo": null,
"myReportingHierarchy": [
{
"_id": "1",
"name": "Dev",
"reportsTo": null,
"depth": NumberLong("0")
},
{
"_id": "2",
"name": "Eliot",
"reportsTo": "Dev",
"depth": NumberLong("1")
},
{
"_id": "3",
"name": "Ron",
"reportsTo": "Eliot",
"depth": NumberLong("2")
},
{
"_id": "4",
"name": "Andrew",
"reportsTo": "Eliot",
"depth": NumberLong("2")
}
]
}

Related

MongoDB: Graphlookup nested documents only returns single document in aggregation

I'm trying the MongoDB aggregation framework to work with nested documents but having trouble returning the expected output, specifically in the $graphLookup stage. In a non-nested schema, it correctly looks up all the documents as defined in the options and returns all. But in a nested one, it only returns one. I have tried $unwind and $replaceRoot as answered here but now it does not work. It would be more understandable through code so here are the samples.
Non-nested document (fileSystem does not count)
db={
"fileSystem": [
{
"_id": "a",
"label": "Root",
"children": [
"b",
],
},
{
"_id": "b",
"label": "Nested folder 1",
"children": [
"c",
"d",
"e"
],
"parent": "a"
},
{
"_id": "c",
"label": "Nested File 1.1",
"parent": "b"
},
{
"_id": "d",
"label": "Nested File 1.2",
"parent": "b"
},
]
}
// Aggregation Query
db.fileSystem.aggregate([
{
"$match": {
"_id": "a"
}
},
{
"$graphLookup": {
"from": "fileSystem",
"startWith": "$children",
"connectFromField": "children",
"connectToField": "_id",
"as": "nest",
"depthField": "level",
"maxDepth": 1
}
},
])
// correct and expected result
[
{
"_id": "a",
"children": [
"b"
],
"label": "Root",
"nest": [
{
"_id": "b",
"children": [
"c",
"d",
"e"
],
"label": "Nested folder 1",
"level": NumberLong(0),
"parent": "a"
},
{
"_id": "d",
"label": "Nested File 1.2",
"level": NumberLong(1),
"parent": "b"
},
{
"_id": "c",
"label": "Nested File 1.1",
"level": NumberLong(1),
"parent": "b"
}
]
}
]
Nested document and query
db={
"fileSystem": [
{
pp: [
{
"_id": "a",
"label": "Root",
"children": [
"b",
],
},
// ... same as previous
]
}
]
}
// Aggregation Query
db.fileSystem.aggregate([
{
"$unwind": "$pp"
},
{
"$replaceRoot": {
"newRoot": "$pp"
}
},
{
"$match": {
"_id": "a"
}
},
{
"$graphLookup": {
"from": "fileSystem",
"startWith": "$pp.children",
"connectFromField": "pp.children",
"connectToField": "pp._id",
"as": "nest",
"depthField": "level",
}
},
])
// incorrect result
[
{
"_id": "a",
"children": [
"b"
],
"label": "Root",
"nest": []
}
]
Expected: https://mongoplayground.net/p/A4yDGUHka58
Bugged: https://mongoplayground.net/p/ZlQyDBrYSZr
$graphLookup searches the collection given in from for matching documents. It uses each document in the pipeline as a starting point, but it does not search for, and will not return documents from the pipline.
In the sample data there is there is only 1 document, so the best you'll get in that case is for the next array to contain the original document.
Playground

Cannot get parent data by mongoDB aggregate graphLookup

Following is the data
[
{
"_id": {
"$oid": "6364f2eee35fc06fa06afb5f"
},
"type": "subbranch",
"parent_id": "635116c18fe4294398842ebb",
"org_name": "Pune - Delhi"
},
{
"_id": {
"$oid": "635116c18fe4294398842ebb"
},
"type": "branch",
"org_name": "Delhi Branch",
"parent_id": "0"
}
]
query which i have written is as follows
// req.params.id is 6364f2eee35fc06fa06afb5f
let id = mongoose.Types.ObjectId(req.params.id);
let data = await organisation.aggregate([
{
$addFields: { "_idString": { "$toString": "$_id" }}
},
{
$graphLookup: {
from: "organisations",
startWith: "$parent_id",
connectFromField: "parent_id",
connectToField: "_idString",
as: "parent"
}
},
{
$match: {_id: id}
},
]);
but in output i get as follow
[
{
"_id": "6364f2eee35fc06fa06afb5f",
"type": "subbranch",
"parent_id": "635116c18fe4294398842ebb",
"org_name": "Pune - Delhi",
"_idString": "6364f2eee35fc06fa06afb5f",
"parent": [
]
}
]
i am getting empty parent array but expected output is array with parent data in it.
any suggestion would be appreciated.
Remember connectFromField expected or extracted from current aggregated collection while connectToField is connected to from orginal collection
DEMO ON https://mongoplayground.net/p/vYDdOgNt9bW
The aggregate query be like
db.collection.aggregate([
{
$addFields: {
"parent_id": {
$convert: {
input: "$parent_id",
to: "objectId",
onError: "$parent_id",
}
}
}
},
{
$graphLookup: {
from: "collection",
startWith: "$parent_id",
connectFromField: "parent_id",
connectToField: "_id",
as: "parent"
}
}
])
Outputs
[
{
"_id": ObjectId("6364f2eee35fc06fa06afb5f"),
"org_name": "Pune - Delhi",
"parent": [
{
"_id": ObjectId("635116c18fe4294398842ebb"),
"org_name": "Delhi Branch",
"parent_id": "0",
"type": "branch"
}
],
"parent_id": ObjectId("635116c18fe4294398842ebb"),
"type": "subbranch"
},
{
"_id": ObjectId("635116c18fe4294398842ebb"),
"org_name": "Delhi Branch",
"parent": [],
"parent_id": "0",
"type": "branch"
}
]

MongoDB aggregation lookup, push output of both collections into sub objects

https://mongoplayground.net/p/xQp-y1iXUtZ
There are 2 collections:
profile
subs
After a lookup, the foreign collection is returned as an array. Since there can be only one element in that array (a sub can only have one profile), we take the first one.
Now, I would like to "push" the "subs" collection into an object as well. There are a lot of fields in "subs".
This is what I have:
[
{
"PROFILE0": {
"_id": "1",
"name": "gk"
},
"_id": "1",
"f1": "f1",
"f2": "f1",
"f3": "f1",
"f4": "f1",
"username": "gk"
},
{
"PROFILE0": {
"_id": "1",
"name": "gk"
},
"_id": "2",
"f1": "f1",
"f2": "f3",
"f3": "f4",
"f4": "f5",
"username": "gk"
}
]
This is what I am looking for:
[
{
"PROFILE0": {
"_id": "1",
"name": "gk"
},
"SUBS": {
"_id": "1",
"f1": "f1",
"f2": "f1",
"f3": "f1",
"f4": "f1",
"username": "gk"
}
},
{
"PROFILE0": {
"_id": "1",
"name": "gk"
},
"SUBS": {
"_id": "2",
"f1": "f1",
"f2": "f3",
"f3": "f4",
"f4": "f5",
"username": "gk"
}
}
]
Essentially the contents of the "local" collection also as an object.
You add projection before lookup,
$project to create a field SUBS and set $$ROOT as the value that is the root document
$lookup to join profile collection, pass SUBS.username as localField, and set PROFILE0 as as value, and we don't need $unset stage
$set same as you did
db.subs.aggregate([
{
$project: {
_id: 0,
SUBS: "$$ROOT"
}
},
{
$lookup: {
from: "profile",
localField: "SUBS.username",
foreignField: "name",
as: "PROFILE0"
}
},
{
$set: {
"PROFILE0": { $arrayElemAt: ["$PROFILE0", 0] }
}
}
])
Playground

mongodb map data in one collection

My intention is to map the reference column based on the id. This is my data in one collection.
[{
"title": "A",
"reference": ["2"],
"id": "1",
"author": ["Doraemon"]
},{
"title": "B",
"reference": [],
"id": "2",
"author": ["Naruto"]
}]
Does anyone can help me how to make it like this
[{
"title": "A",
"reference": ["B"],
"id": "1",
"author": ["Doraemon"]
},{
"title": "B",
"reference": [],
"id": "2",
"author": ["Naruto"]
}]
You can do self lookup
db.collection.aggregate([
{
"$lookup": {
"from": "collection",
"localField": "reference",
"foreignField": "id",
"as": "selfJoin"
}
},
{
$addFields: {
reference: "$selfJoin.title"
}
},
{
$project: {
selfJoin: 0
}
}
])
Working Mongo playground

get nested model reference from mongodb

I have code below to get bookmarked blog of user
Question -> I want to also need the user object with selected field
Bookmarkblog.aggregate([{
$lookup:
{
from: "blogs",
localField: "blog",
foreignField: "_id",
as: "blog"
}
}, {
$match: { "user": mongoose.Types.ObjectId(req.headers.userid) }
}])
current output
[
{
"_id": "5a82ce0d80f62b18bc5ac5bf",
"blog": [
{
"_id": "5a696a31f78861dd29bec5bd",
"user": "59bbbe071b4a358f43dc0cbf",
"category": "59c3b5022ad1854d496cfb8b",
"image": [
"57904805-imac_pro_large.jpg"
],
"tags": [
"Mac"
],
"content": "",
"title": "iMac Pro, the most powerful Mac ever",
"created": "2018-01-25T05:25:05.025Z",
"__v": 0
}
],
"user": "59e5a62427543c54603050de",
"created": "2018-02-13T11:37:49.071Z",
"__v": 0
}
]