In MongoDB Not able to find sub-documents based on IDs - node.js

I'm using MongoDb (as part of MongoJS) in Node. I using subdocuments and allocating IDs to the sub-docs also.
when I do a query based on the main documents it returns me the whole document, but when I try to find the sub-document based on its ID it do't return me any result. In mongoose I have declared a seperate schema for results field having its own ID.
It is to note that I am using arrays within arrays, for the result field.
Following is the console output of this scenario.
>db.tests.find({"_id":ObjectId("56563e92c8be03ec1a341374")}).pretty();
"_id" : ObjectId("56563e92c8be03ec1a341374"),
"test" : 2,
"startAt" : ISODate("2015-11-25T23:04:50Z"),
"endedAt" : ISODate("2015-11-25T23:04:50Z"),
"results" : [
{
"_id" : ObjectId("56563e92c8be03ec1a341375"),
"second" : [
{
"sec" : 50,
"avg" : 40.6,
"grt" : 1.2
}
]
}
],
>db.tests.find({"_id":ObjectId("56563e92c8be03ec1a341375")}).pretty();
>

You cannot search for subdocuments only by their ID in mongoDb. You have to always start from the main document i.e...search for the document that has an "results" array that contains the subdocument you are looking for:
db.test.find({ "results._id" : ObjectId("56563e92c8be03ec1a341375") });
if you want the output document to contain only the subdocument you were looking for (excluding other subdocuments it the array) you can use projection {"results.$":1}:
db.test.find({ "results._id" : ObjectId("56563e92c8be03ec1a341375") },{"results.$" : 1});
It will give you this output:
{
"_id": ObjectId("56563e92c8be03ec1a341374"),
"results": [{
"_id": ObjectId("56563e92c8be03ec1a341375"),
"second": [{
"sec": 50,
"avg": 40.6,
"grt": 1.2
}]
}]
}

Related

How to add/update in array document with condition in mongoose

I need to perform the upsert operation. Below is my document structure.
I want to update the spin_details array when there is a match found with package_id but with two conditions i.e. user_id & spin_details.package_id.
If there is a match with user_id but there is no match with spin_details.package_id then some package information has to be pushed into the spin_details array. If there is no match with user_id(only) itself then it should be able to insert a new document.
{
"_id" : ObjectId("6234ffa6bd36b0e5a05ac913"),
"user_id" : ObjectId("6230e5e2b1530b407cedeb1d"),
"__v" : 0,
"is_active" : true,
"spin_details" : [
{
"package_id" : ObjectId("6230e5e2b1530b407cedeb9d"),
"spin_count" : 10,
"_id" : ObjectId("6234ffa6f390e1fafa8e215b")
},
{
"package_id" : ObjectId("6230e5e2b1530b407cedeb2a"),
"spin_count" : 25,
"_id" : ObjectId("6234ffa6f390e1fafa8e409b")
}
]
}
I can do this using multiple different queries and then based on the result value. How can I do this with a single mongoose query for this situation?

MongoDB query with embedded document in array (3 levels)

I had this data on my MongoDB database and I would like to get only the second array about blades.
{
"_id" : ObjectId("..."),
"name" : "Westereems",
"country" : "Netherlands",
"turbines" : [
{
"turbine_id" : ObjectId("..."),
"blades" : [
{
"blade_id" : ObjectId("..."),
"position" : 2,
"size" : 50,
}
]
}
]
}
I only want one return with blade_id, position and size. I tried this query and I didn't have the expectable result:
db.collection("windfarms").find({"turbines.blades.blade_id" : ObjectId("...")}, {"turbines.blades.$" : 1, "_id" : 0})
Regards,
You can use this query, it's not an optimal query for large array's items but if you have only above items then you can use it.
you can also go with aggregation to make it more optimal.
db.collection("windfarms").find({"turbines.blades.blade_id" : ObjectId("...")}, {"turbines.blades.blade_id":1,"turbines.blades.position":1,"turbines.blades.size":1,"_id":0})

Querying a property that is in a deeply nested array

So I have this document within the course collection
{
"_id" : ObjectId("53580ff62e868947708073a9"),
"startDate" : ISODate("2014-04-23T19:08:32.401Z"),
"scoreId" : ObjectId("531f28fd495c533e5eaeb00b"),
"rewardId" : null,
"type" : "certificationCourse",
"description" : "This is a description",
"name" : "testingAutoSteps1",
"authorId" : ObjectId("532a121e518cf5402d5dc276"),
"steps" : [
{
"name" : "This is a step",
"description" : "This is a description",
"action" : "submitCategory",
"value" : "532368bc2ab8b9182716f339",
"statusId" : ObjectId("5357e26be86f746b68482c8a"),
"_id" : ObjectId("53580ff62e868947708073ac"),
"required" : true,
"quantity" : 1,
"userId" : [
ObjectId("53554b56e3a1e1dc17db903f")
]
},...
And I want to do is create a query that returns all courses that have a specific userId in the userId array that is in the steps array for a specific userId. I've tried using $elemMatch like so
Course.find({
"steps": {
"$elemMatch": {
"userId": {
"$elemMatch": "53554b56e3a1e1dc17db903f"
}
}
}
},
But It seems to be returning a empty document.
I think this will work for you, you have the syntax off a bit plus you need to use ObjectId():
db.Course.find({ steps : { $elemMatch: { userId:ObjectId("53554b56e3a1e1dc17db903f")} } })
The $elemMatch usage is not necessary unless you actually have compound sub-documents in that nested array element. And also is not necessary unless the value being referenced could possibly duplicate in another compound document.
Since this is an ObjectId we are talking about, then it's going to be unique, at least within this array. So just use the "dot-notation" form:
Course.find({
"steps.userId": ObjectId("53554b56e3a1e1dc17db903f")
},
Go back and look at the $elemMatch documentation. In this case, the direct "dot-notation" form is all you need

Contains Query into MongoDB Array using Mongoose

I'm trying to query into following document and want to list all document which contains TaxonomyID "1" in "TaxonomyIDs" field.
...
"Slug" : "videosecu-600tvl-outdoor-security-surveillance",
"Category" : "Digital Cameras",
"SubCategory" : "Surveillance Cameras",
"Segment" : "",
"Usabilities" : [
"Dome Cameras",
"Night Vision"
],
"TaxonomyIDs" : [
1,
12,
20,
21,
13
],
"Brand" : "VideoSecu",
...
Totally stuck!
Model.find({TaxonomyIDs: 1}, function(error, models) {
//put code to process the results here
});
mongodb interprets the query conditions above as "match any document where the TaxonomyIDs array contains 1".

Getting counts of embedded collections in a MongoDB Document

I am using MongoDB and the 10Gen node.js driver.
I have a collection in MongoDB that has docs similar to this:
{
_id: ObjectId( "500310affdc47af710000001" ),
name:'something',
tags:['apple','fruit','red'],
created: Date( 1342378221351 )
}
What I would like to get is look at all the documents and get a distinct count of all tags across all documents in the collection. I tried the group function and got this:
> db.photos.group(
... {cond:{}
... ,key:{tags:true}
... ,initial:{count:0}
... ,reduce:function(doc,out){out.count++}
... ,finalize:function(out){}});
[
{
"tags" : null,
"count" : 35
},
{
"tags" : [
"#strawberry",
"#friutpicture"
],
"count" : 1
}
]
Which is not right. I can get the distinct without the counts like this:
> db.photos.distinct('tags')
[
"#friutpicture",
"#strawberry",
"#factory",
"#wallpaper",
"#bummber",
"#test",
"#fire",
"#watermark"
]
but I need the counts.
You can use the following in the new Aggregation Framework (2.1+):
> db.photos..aggregate([{$unwind:"$tags"},
{$group:{_id:"$tags"}},
{$group:{_id:"DistictCount",count:{$sum:1}}}])
Your result will be:
{
"result" : [
{
"_id" : "DistictCount",
"count" : 8
}
],
"ok" : 1
}
The group function won't do what you need because you need to "unroll" the tag array before you can group on it and that means you need a map function that emits each tag in a document, as well as a reduce. You can use map/reduce if you are stuck on 2.0 or earlier and can't use aggregation framework. Here is an example that may help.

Resources