Aggrerate nested objectid - mongodb

I have documents like this:
{
"_id": "...",
"collectionName": "blabla",
"items": ["ObjectID("1")","ObjectID("2")"],
}
items collection:
{
"_id": "1",
"name": "item name",
"size": 3
},
{
"_id": "2"
"name": "item name 2",
"size": 4
}
Output:
{
"_id": "...",
"collectionName": "blabla",
"items": ["ObjectID("1")","ObjectID("2")"],
"totalSize": 7
}
I'm trying to use aggrerate to sum all items size which is referenced by ObjectID
is this even possible? I couldn't find any information about it

Related

How to recursively query the nested documents of mogodb?

{
"id": "1505036191456227329",
"materialList": [
{
"id": "1505035441229459457",
"model": "",
"parentId": "0",
},
{
"id": "1505035441229459458",
"model": "",
"parentId": "1505035441229459457",
}, {
"id": "1505035441229459459",
"model": "",
"parentId": "1505035441229459457",
},{
"id": "1505035441229459460",
"model": "",
"parentId": "1505035441229459459",
}
]
}
this is my data,I want to find all sub data IDS with ID 1505035441229459457 under the materiallist。
The result of the query is 1505035441229459458,1505035441229459459,1505035441229459460
You will have to use $elemMatch for this.
Ex -> db.collection.find( { materialList: { $elemMatch: {id:
1505035441229459457 } } })

Need to aggregate and return results based on document nested array

I have the following document:
{
"_id": ObjectId("10..."),
"ownerName": "Merchant 10",
...,
"stores": [
{
"id": ObjectId("20..."),
"storeName": "Store 20"
},
{
"id": ObjectId("21..."),
"storeName": "Store 21"
}
]
},
{
"_id": ObjectId("11..."),
"ownerName": "Merchant 11",
...,
"stores": [
{
"id": ObjectId("22..."),
"storeName": "Store 22"
}
]
}
Is it possible with aggregate to return paginated results based on nested array "stores", and end up with the following result:
{
"_id": "20...",
"ownerName": "Merchant 10",
"storeName": "Store 20"
}, {
"_id": "21...",
"ownerName": "Merchant 10",
"storeName": "Store 21"
}, {
"_id": "22...",
"ownerName": "Merchant 11",
"storeName": "Store 22"
},
So basically, I would like to be able to share owner info but returning result based on stores.
I tried another way with a stores document but with my specific requirement, I ended up with a circular dependency.
Thanks
Using unwind on stores you can flatten out the documents. After that, just project the fields you need:
db.mycollection.aggregate( [
{ $unwind: "$stores" },
{ $project: { "ownerName": 1, "storeName": "$stores.storeName" } }
] )

Nested lookup in mongodb

{
"_id": "445454",
"students": ["7894556", "5454454"]
}
This is my actual data. After first lookup I got a result like:
{
"_id": "445454",
"students": [{
"name": "Jose",
"parent": "45566622"
},{
"name": "Mathew",
"parent": "7889665"
}]
}
but actual answer I required is something like this
{
"_id": "445454",
"students": [{
"name": "Jose",
"parent": {
"_id": "45566622",
"name": "Cristy"
}
}, {
"name": "Mathew",
"parent": {
"_id": "7889665",
"name": "Abraham"
}
}]
}
somebody please help me. I not expert in mongodb.

Nested grouping of array

There are 3 master collection of category , subcategory and criteria each, i will be building framework with any possible combination of category , subcategory and criteria which will be stored as below-
framework document is added below having list of criteriaconfig as embedded object which further have single object of category , subcategory and criteria. you can refer criteriaconfig as link table that u call in mysql.
[
{
"id": "592bc3059f3ad715002b2331",
"name": "Framework1",
"description": "framework 1 for testing",
"criteriaConfigs": [
{
"id": "592bc3059f3ad715002b232f",
"category": {
"id": "591c2f5faa187956b2d0fb39",
"name": "category1",
"description": "category1",
"deleted": false,
"createdDate": 1495019359558
},
"subCategory": {
"id": "591c2f5faa187956b2d0fb83",
"name": "subCat1",
"description": "subCat1"
},
"criteria": {
"id": "591c2f5faa187956b2d0fbad",
"name": "criteria1",
"measure": "Action"
}
},
{
"id": "592bc3059f3ad715002b232e",
"category": {
"id": "591c2f5faa187956b2d0fb37",
"name": "Process",
"description": "Enagagement"
},
"subCategory": {
"id": "591c2f5faa187956b2d0fb81",
"name": "COMM / BRANDING",
"description": "COMM / BRANDING"
},
"criteria": {
"id": "591c2f5faa187956b2d0fba9",
"name": "Company representative forgets about customer on hold",
"measure": ""
}
} ]
},
{
"id": "592bc3059f3ad715002b2332",
"name": "Framework2",
"description": "framework 2 for testing",
"criteriaConfigs": [
{
"id": "592bc3059f3ad715002b232f",
"category": {
"id": "591c2f5faa187956b2d0fb39",
"name": "category1",
"description": "category1"
},
"subCategory": {
"id": "591c2f5faa187956b2d0fb83",
"name": "subCat1",
"description": "subCat1"
},
"criteria": {
"id": "591c2f5faa187956b2d0fbad",
"name": "criteria1",
"measure": "Action"
}
}
]
}
]
i need a view containing framework that will contain all list of category and inside category there will be list of added subcategory and inside subcategory will have list of criteria for single framework.
expected result -
[
{
"id": "f1",
"name": "Framework1",
"description": "framework 1 for testing",
"categories": [
{
"id": "c2",
"name": "category2",
"description": "category2",
"subCategories": [
{
"id": "sb1",
"name": "subCat1",
"description": "subCat1",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr2",
"name": "criteria2",
"measure": "Action"
},
{
"id": "cr3",
"name": "criteria3",
"measure": "Action"
}]
},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}]
},
{
"id": "c1",
"name": "category1",
"description": "category1",
"subCategories": [
{
"id": "sb3",
"name": "subCat3",
"description": "subCat3",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr2",
"name": "criteria2",
"measure": "Action"
}
]},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}
]
}]
},
{
"id": "f2",
"name": "Framework2",
"description": "framework 2 for testing",
"categories": [
{
"id": "c2",
"name": "category2",
"description": "category2",
"subCategories": [
{
"id": "sb4",
"name": "subCat5",
"description": "subCat5",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr3",
"name": "criteria3",
"measure": "Action"
}]
},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}]
},
{
"id": "c1",
"name": "category1",
"description": "category1",
"subCategories": [
{
"id": "sb3",
"name": "subCat3",
"description": "subCat3",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr2",
"name": "criteria2",
"measure": "Action"
}
]},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}
]
}]
}
]
Note - Category document doesn't have any reference to subcategory and same way subcategory doesn't have any reference to criteria object currently as they are master data and are generic , framework is created with their combination dynamically.
If you want to try to do all the work in the aggregation, you could group first by subcategory, then by category like:
db.collection.aggregate([
{$unwind:"$criteriaConfigs"},
{$project:{
_id:0,
category:"$criteriaConfigs.category",
subCategory:"$criteriaConfigs.subCategory",
criteria:"$criteriaConfigs.criteria"
}},
{$group:{
_id:{"category":"$category","subCategory":"$subCategory"},
criteria:{$addToSet:"$criteria"}
}},
{$group:{
_id:{"category":"$_id.category"},
subCategories:{$addToSet:{subCategory:"$_id.subCategory",
criteria:"$criteria"}}
}},
{$project:{
_id:0,category:"$_id.category",
subCategories:"$subCategories"
}}
])
Depending on how you plan to us the return data, it may be more efficient to return each unique combination:
db.collection.aggregate([
{$unwind:"$criteriaConfigs"},
{$group:{
_id:{
category:"$criteriaConfigs.category.name",
subCategory:"$criteriaConfigs.subCategory.name",
criteria:"$criteriaConfigs.criteria.name"
}
}},
{$project:{
_id:0,
category:"$_id.category",
subCategory:"$_id.subCategory",
criteria:"$_id.criteria"
}}
])
I'm not sure from your question what shape you are expecting the return data to have, so you may need to adjust for that.

MongoDB: Return deeply nested document from it's id regardless of level

I have a collection consisting of documents that are made up of an id, name and an array of items; the array in each document is supposed to nest other documents of the same structure when applicable, and there is no limit to how many nested arrays of documents there are (nested documents can also have nested documents).
Using the MongoClient package, I'm trying to query my collection and return a document based on it's id, regardless of it's location in the data (be it at the top level or 3 levels down).
So far I can return any top level data okay, but my query is not finding any nested data. I've seen similar questions where the data structure is limited and consistent, but as my data is dynamic and multi-layered, I haven't find a solution that fits this particular issue.
Here's my data:
[
{
"_id": 1,
"name": "Test 1",
"items": []
},
{
"_id": 2,
"name": "Test 2",
"items": [
{
"_id": 3,
"name": "Test 3",
"items": []
},
{
"_id": 4,
"name": "Test 4",
"items": [
{
"_id": 6,
"name": "Test 6",
"items": []
}
]
}
]
},
{
"_id": 5,
"name": "Test 5",
"items": []
}
]
Here's my Mongo query:
MongoClient.connect(connString, function(err, db) {
var collection = db.collection('items');
collection.findOne({_id: ObjectID("4")}, function(err, result) {
console.log(result);
});
db.close();
});
And result is intended to return the following, but returns null instead:
{
"_id": 4,
"name": "Test 4",
"items": [
{
"_id": 6,
"name": "Test 6",
"items": []
}
]
}
Can anyone share a solution as to how I can retrieve my data as intended?
It is not possible to query an infinate amount of document of documents due to the change of properties at each level. See Query Selectors (https://docs.mongodb.com/manual/reference/operator/query/#query-selectors) for a list of selectors that can be used.
However if it's possbile to limit or give a depth limit on the items then you could use a query such as:-
db.col.find( {$or: [ { "_id" : id }, { "items._id" : id }, { "items.items._id" : id }, { "items.items.items._id" : id } ] } );
If it's not possible to give a depth limit I'd advise re-modeling the document in to something like:
[
{
"_id": 1,
"name": "Test 1"
},
{
"_id": 3,
"name": "Test 3",
"parentId": 2
},
{
"_id": 6,
"name": "Test 6",
"parentId": 4
},
{
"_id": 4,
"name": "Test 4",
"parentId": 2
},
{
"_id": 2,
"name": "Test 2",
},
{
"_id": 5,
"name": "Test 5",
}
]
Then you could do a simple find by _id query:
> db.collection.find({_id: 4})
{ "_id" : 4, "name" : "Test 4", "parentId" : 2 }
If you also need to retain the document structure of the query you can use the $graphLookup aggregation stage.