mongodb find all records with subdocument id equals to - mongodb

i have the following collection records:
> db.products.find(ObjectId("53a9a6aad901f2961403fc9b")).pretty()
{
"_id" : ObjectId("53a9a6aad901f2961403fc9b"),
"code" : "N39",
"name" : {
"en-UK" : "N39"
},
"weight" : [
90
],
"collectionId" : ObjectId("53a9a6a8d901f2961403fbe2"),
"fabric_composition" : [
{
"fabricId" : ObjectId("53a9a6a9d901f2961403fc69"),
"value" : 70
}
{
"fabricId" : ObjectId("53a9a6a9d901f2961403fc6a"),
"value" : 30
}
],
"visible" : "true",
"manufacturer" : "53a859d9d901f2e8f81ac83b"
}
and
> db.fabric.find().pretty()
{
"_id" : ObjectId("53a9a6a9d901f2961403fc69"),
"name" : [
{
"en-UK" : "Recycled Organic Cotton"
}
]
}
{
"_id" : ObjectId("53a9a6a9d901f2961403fc6a"),
"name" : [
{
"en-UK" : "Recycled Polyester"
}
]
}
how do i query the mongodb collection products to list all products that have a fabric_composition with ObjectId for Recycled Organic Cotton as an example?
any advice much appreciated

You need to use use dot notation to query subdocuments:
db.products.find({
"fabric_composition.fabricId" : ObjectId("53a9a6a9d901f2961403fc69")
});
This query will return all documents that have at least one sub-document with fabricId you're looking for.

Related

MongoDB - query for a nested item inside a collection

i have a mongodb collection "result" with data like
{ "_id" : {
"user" : "Howard",
"friend" : "Sita"
},
"value" : {
"mutualFriend" :[ "Hanks", "Bikash", "Shyam", "Bakshi" ]
}
}
{ "_id" : {
"user" : "Shiva",
"friend" : "Tom"
},
"value" : {
"friendList" :[ "Hanks", " Tom", " Karma", " Hari", " Dinesh" ]
}
}
{ "_id" : {
"user" : "Hari",
"friend" : "Shiva"
},
"value" : {
"mutualFriend" :[ "Tom", "Karma", "Dinesh" ]
}
}
Now, here i want to query whole Document having value.mutualFriend. how can i get the result?
Expected Output
{ "_id" : {
"user" : "Howard",
"friend" : "Sita"
},
"value" : {
"mutualFriend" :[ "Hanks", "Bikash", "Shyam", "Bakshi" ]
}
}
{ "_id" : {
"user" : "Hari",
"friend" : "Shiva"
},
"value" : {
"mutualFriend" :[ "Tom", "Karma", "Dinesh" ]
}
}
i have large number of document in MongoDB collection, containing value.friendList and value.mutualFriend and then i want to find only documents with value.mutualFriend
db.collection.find({"value.mutualFriend.0" : { $exists : true }})
Its just make sure that the 0th element exists. you can customize your query over various array length.

Mongodb embedded document - aggregation query

I have got the below documents in Mongo database:
db.totaldemands.insert({ "data" : "UKToChina", "demandPerCountry" :
{ "from" : "UK" , to: "China" ,
"demandPerItem" : [ { "item" : "apples" , "demand" : 200 },
{ "item" : "plums" , "demand" : 100 }
] } });
db.totaldemands.insert({ "data" : "UKToSingapore",
"demandPerCountry" : { "from" : "UK" , to: "Singapore" ,
"demandPerItem" : [ { "item" : "apples" , "demand" : 100 },
{ "item" : "plums" , "demand" : 50 }
] } });
I need to write a query to find the count of apples exported from UK to any country.
I have tried the following query:
db.totaldemands.aggregate(
{ $match : { "demandPerCountry.from" : "UK" ,
"demandPerCountry.demandPerItem.item" : "apples" } },
{ $unwind : "$demandPerCountry.demandPerItem" },
{ $group : { "_id" : "$demandPerCountry.demandPerItem.item",
"total" : { $sum : "$demandPerCountry.demandPerItem.demand"
} } }
);
But it gives me the output with both apples and plums like below:
{ "_id" : "apples", "total" : 300 }
{ "_id" : "plums", "total" : 150 }
But, my expected output is:
{ "_id" : "apples", "total" : 300 }
So, How can I modify the above query to return only the count of apples exported from UK ?
Also, is there any other better way to achieve the output without unwinding ?
You can add another $match to get only apples.
As you have embedded document structure and performing aggregation, $unwind is required here. The alternate option could be map and reduce. However, unwind is most suitable here.
If you are thinking about performance, unwind shouldn't cause performance issue.
db.totaldemands.aggregate(
{ $match : { "demandPerCountry.from" : "UK" ,
"demandPerCountry.demandPerItem.item" : "apples" } },
{ $unwind : "$demandPerCountry.demandPerItem" },
{ $group : { "_id" : "$demandPerCountry.demandPerItem.item",
"total" : { $sum : "$demandPerCountry.demandPerItem.demand"
} } },
{$match : {"_id" : "apples"}}
);

MongoDB and aggragate the embeded document

I am new to mongoDB and I came across a problem. The data was imported according to official doc.
As you can see, each of restaurant has a grades array and the nested document contains a score field. What I want to do is according to the average score of each restaurant's grades and retrive the restaurant that has the top average score. This may need to use mongoDB's aggregate method but the document doesn't cover the nested document situation and I googled but without a result. There's a similar question on this site but it's not so clear.
[
{ "_id" : ObjectId("56a9f39cae1902590811dffc"),
"address" : { "building" : "284",
"coord" : [ -73.9829239, 40.6580753 ],
"street" : "Prospect Park West",
"zipcode" : "11215" },
"borough" : "Brooklyn",
"cuisine" : "American ",
"grades" : [ { "date" : ISODate("2014-11-19T00:00:00Z"), "grade" : "A", "score" : 11 },
{ "date" : ISODate("2013-11-14T00:00:00Z"), "grade" : "A", "score" : 2 },
{ "date" : ISODate("2012-12-05T00:00:00Z"), "grade" : "A", "score" : 13 },
{ "date" : ISODate("2012-05-17T00:00:00Z"), "grade" : "A", "score" : 11 } ],
"name" : "The Movable Feast",
"restaurant_id" : "40361606" },
...
]
Using the mongo shell, try the below , change "collecttionname" to the name of your your restaurant collections
db.collectionname.aggregate( { '$unwind' : '$grades' } , { '$group' : { '_id' : '$_id' , 'average' : { $avg : '$grades.score' } } } , { '$sort' : { 'average' : -1 } } , { '$limit' : 1 } )

mongodb Embedded document search on parent and child field

I have a nested embedded document CompanyProduct below is structure
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca3"),
"CompanyID" : 90449,
"Name" : Company1,
"CompanyDepartment" : [
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca4")
"DepartmentID" : 287,
"DepartmentName" : "Stores",
"DepartmentInventory" : [
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 1,
"ProductName" : "abc",
"Quantity" : 100
},
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 2,
"ProductName" : "xyz",
"Quantity" : 1
}
],
}
],
}
There can be N no of companies and each company can have N number of departments and each department can have N number of products.
I want to do a search to find out a particular product quantity under a particular company
I tried below query but it does not work. It returns all the products for the specific company, the less than 20 condition doesn't work.
db.CompanyProduct.find({$and : [{"CompanyDepartment.DepartmentInventory.Quantity":{$lt :20}},{"CompanyID":90449}]})
How should the query be?
You are searching from companyProduct's sub documents. So it will return you companyProduct whole document, it is NoSQL database , some how we do not need to normalize the collection , but your case it has to be normalize , like if you want to EDIT/DELETE any sub document and if there are thousand or millions of sub document then what will you do ... You need to make other collection with the name on CompanyDepartment and companyProduct collection should be
productCompany
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca3"),
"CompanyID" : 90449,
"Name" : Company1,
"CompanyDepartment" : ['53d213c5ddbb1912343a8ca4'],
}
and other collection companyDepartment
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca4")
"DepartmentID" : 287,
"DepartmentName" : "Stores",
"DepartmentInventory" : [
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 1,
"ProductName" : "abc",
"Quantity" : 100
},
{
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 2,
"ProductName" : "xyz",
"Quantity" : 1
}
],
}
after this you got array of companyDeparment' ID and only push and pull query will be used on productCompany
A Solution can be
db.YourCollection.aggregate([
{
$project:{
"CompanyDepartment.DepartmentInventory":1,
"CompanyID" : 1
}
},{
$unwind: "$CompanyDepartment"
},{
$unwind: "$CompanyDepartment.DepartmentInventory"
},{
$match:{$and : [{"CompanyDepartment.DepartmentInventory.Quantity":{$lt :20}},{"CompanyID":90449}]}
}
])
the result is
{
"result" : [
{
"_id" : ObjectId("53d213c5ddbb1912343a8ca3"),
"CompanyID" : 90449,
"CompanyDepartment" : {
"DepartmentInventory" : {
"_id" : ObjectId("53b7b92eecdd765430d763bd"),
"ProductID" : 2,
"ProductName" : "xyz",
"Quantity" : 1
}
}
}
],
"ok" : 1
}

how to use aggregation of mongodb

From the data as given below, I want to sum all Values fields.
Please let me know how can I do it using aggregation functionality of mongodb.
{"MetricRecord":
{ "SchemaVersion" : "0.12",
"Product": {
"ProductName" : "abc",
"ProductVersion": "7.5.0.1" ,
"ProductId" : "1234567890ABDFGH12345",
"InstanceId" : "12345BA32",
"InstanceName" : "1234SS123",
"SystemId" : "somehost.com"
},
"Tenant" : {
"CustomerId" : "222-555-124",
"ServiceCode": "xyzxyzxyz12345yyy"
},
"Metrics" : [
{
"ReportType" :[
{ "report" : "billing" },
],
"LogTime" : "2013-12-08T12:34:56:01Z" ,
"Type" : "AuthorizedUsers",
"SubType" : "registered",
"Value" : "125",
"UnitOfMeasure": "USD",
"Period" : {
"StartTime" : "2013-12-07T00:00:00:01Z",
"EndTime" : "2013-12-08T00:00:00:01Z"
}
},
{
"ReportType" :[
{ "report" : "billing" }
],
"LogTime" : "2013-12-08T12:34:56:01Z" ,
"Type" : "NumberOfTickets",
"SubType" : "resolved",
"Value" : "430",
"UnitOfMeasure": "USD",
"Period" : {
"StartTime" : "2013-12-07T00:00:00:01Z",
"EndTime" : "2013-12-08T00:00:00:01Z"
}
}
]
}
}
So, results which I expect from summation of values is 430+125 i.e. 555
Your document contains string value for MetricRecord.Metrics[index].Value field and i am not sure why are you trying to sum up the string values. if it is a typo and your document contains numerical values for MetricRecord.Metrics[index].Value field then you can try the following query
db.metrics.aggregate([
{$unwind:"$MetricRecord.Metrics"},
{$group:{_id:"$_id",sum:{$sum:"$MetricRecord.Metrics.Value"}}}
])
In the above document posted, if your value field is like
MetricRecord.Metrics[0].Value is 125(not "125")
MetricRecord.Metrics[1].Value is 430(not "430")
you will get the following output
{
"result" : [
{
"_id" : ObjectId("xxxxxxxxxxxxxxxxxxxxxxxx"),
"sum" : 555
}
],
"ok" : 1
}
The above sample query is composed assuming you have the default mongodb "_id" field and you are using a metrics collection. You have to manipulate the query as per you requirements.