what it means by "populate" in mongoose - node.js

so generally what is "populate"? referring to some action to the database.
I have heard it before but never got it right..

If you have a document pointing to another document (i.e. contains an ID reference), populate will fetch the referenced document.
For instance, if you have:
{
"__id" : "a",
"className" : "astroPhysics",
"teacher" : "b"
}
and
{
"__id" : "b",
"teacherName" : "John Smith"
}
getting a and populating teacher will give the following result:
{
"__id" : "a",
"className" : "astroPhysics",
"teacher" : {
"__id" : "b",
"teacherName" : "John Smith"
}
}

Related

MongoDB DBRefs to query reference collection field

I have two different collection in two different MongoDB databases.
Collection users in db1:
{
"_id" : "xyz",
"name" : "John",
"project_id" : "abc"
}
Collection project in db2:
{
"_id" : "abc",
"regionCode" : "1AB"
}
Now I want to get list of all users who belong to region 1AB. How do I achieve that.
I read about DBRefs. So I changed structure of collections users but still i can not query directly to reference collection attribute directly
collection users new structure :
{
"_id" : "xyz",
"name" : "John",
"project_id" : "abc",
"projectData" : {
"$ref" : "project",
"$id" : "abc",
"$db" : "db2"
}
}
Now how do I get list of all users that belong to project regioncode 1AB.
I am using nodejs native client

update array in mongoose which matches the condition

my schema looks like
{
qty:{
property1:{
//something
}
property2:[{
size:40,
color:"black",
enabled:"true"
}]
}
}
property 2 is array what i want to do is update those array object whose enabled is true in single query
I tried writing the following query
db.col.update({
"qty.property2.enabled" = "true"
}, {
"qty.property2.color" = "green"
}, callback)
but it is not working
error:
[main] Error: can't have . in field names [qty.pro.size]
db.col.update({"qty.property2.enabled":"true"},{$set: {'qty.property2.$.color': 'green'}}, {multi: true})
this is the way to update element inside array.
equal sign '=' cannot be used inside object
updating array is done using $
Alternative solution for multiple conditions:
db.foo.update({
_id:"i1",
replies: { $elemMatch:{
_id: "s2",
update_password: "abc"
}}
},
{
"$set" : {"replies.$.text" : "blah"}
}
);
Why
So I was looking for similar solution as this question, but in my case I needed array element to match multiple conditions and using currently provided answers resulted in changes to wrong fields.
If you need to match multiple fields, for example let say we have element like this:
{
"_id" : ObjectId("i1"),
"replies": [
{
"_id" : ObjectId("s1"),
"update_password": "abc",
"text": "some stuff"
},
{
"_id" : ObjectId("s2"),
"update_password": "abc",
"text": "some stuff"
}
]
}
Trying to do update by
db.foo.update({
_id:"i1",
"replies._id":"s2",
"replies.update_password": "abc"
},
{
"$set" : {"replies.$.text" : "blah"}
}
);
Would result in updating to field that only matches one condition, for example it would update s1 because it matches update_password condition, which is clearly wrong. I might have did something wrong, but $elemMatch solution solved any problems like that.
Suppose your documet looks like this.
{
"_id" : ObjectId("4f9808648859c65d"),
"array" : [
{"text" : "foo", "value" : 11},
{"text" : "foo", "value" : 22},
{"text" : "foobar", "value" : 33}
]
}
then your query will be
db.foo.update({"array.value" : 22}, {"$set" : {"array.$.text" : "blah"}})
where first curly brackets represents query criteria and second one sets the new value.

Find field value that is found in most documents

Suppose there are documents that represents books and there is a field called author. What aggregation(s) can retrieve the author value that is found in most documents? Or rephrased, the author that has written most books?
In case it's not clear from the tag, the question is referring to Elasticsearch.
e.g.
{
"name" : "Book1"
"author" : "John"
},
{
"name" : "Book3"
"author" : "Mike"
},
{
"name" : "Book2"
"author" : "John"
},
{
"name" : "Book4"
"author" : "Frank"
}
For the above data, John must be returned since there are 2 documents with him as an author, while only one book by the others.
I've tried with value_count and cardinality, but this only returns the count and not the value itself.
Actually this I found this is quite simple using terms aggregation. Left it, maybe other find this useful.
Reference
e.g. From data from above:
{
"aggs": {
"author_count": {
"terms": {
"size": 2,
"field": "book.author"
}
}
}

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

How to get the double quotes arround number typed field from MongoDB aggregation query result?

Scenario: I have a collection 'People' with following documents
{
"_id" : ObjectId("512bc95fe835e68f199c8686"),
"name": "David",
"age" : 78
},
{ "_id" : ObjectId("512bc962e835e68f199c8687"),
"name" : "Dave",
"age" : 35
}
When I query using following code from Node.js
db.articles.aggregate(
{ $match : { author : "Dave" } }
);
The output will be like:
{ "_id" : ObjectId("512bc962e835e68f199c8687"),
"name" : "Dave",
"age" : 35
}
Issues: The above is just a sample of the actual scenario, I want the 'age' filed value to be embedded in double quotes i.e for above quoted example it should be like "age": "35".
That is full resultant document should be like following:
{ "_id" : ObjectId("512bc962e835e68f199c8687"),
"name" : "Dave",
"age" : "35"
}
Consider I have huge number of documents how efficiently I can achieve the same to get the desired output?
Question: Can someone help out with bright and efficient way to achieve the same?

Resources