Mongoose. number of entries for specific property - mongodb

I have collection People.
Every person in this collection has favorite color. here example of person
{
id:123,
color:'red',
...
...
}
What is an elegant way to go through collection People, and
query all possible colors form that collection and how many people love that color?
Example of output:
'green':125,
'yellow': 76
etc...
Many thanks for help!!

Use the aggregation framework.
db.collection.aggregate( [
{$group: {_id:"$color",
numLiking:{$sum:1}
} }
] );
You'll get back something like:
[ { _id:"red", numLiking:7 }, { _id:"green", numLiking:17 }, ... ]

Related

How to write a mongo query that returns fields with the expected results?

For instance I am trying to bring up the organization ids that are tagged to multiple countries in db.
db.collection.find({"Region":{$in:["CHINA","JAPAN","SOUTH_KOREA"]}})
this doesnot give me the results that they have all 3 countries in the same document. Obviously $where does not work which I can query to bring up the fields that have more than 1 country in it.
Trying this for 2 days and need your help.
Thanks in advance.
Use $all
The $all operator selects the documents where the value of a field is an array that contains all the specified elements.
db.collection.find({"Region":{ $all :["CHINA","JAPAN","SOUTH_KOREA"] } })
i hope this will go acording youre need's:
db.collection.find({
$and: [
{ Region: {$in: /\bCHINA\b/i} },
{ Region: {$in: /\bJAPAN\b/i} },
{ Region: {$in: /\bSOUTH_KOREA\b/i} }
]
})
If I'm understanding your question correctly, you are trying to match a document where the Region key is a list conataining all three countries.
db.collection.find({$and: [
{Region: {$in: ["CHINA"]}},
{Region: {$in: ["JAPAN"]}},
{Region: {$in: ["SOUTH_KOREA"]}}
])
If so, this should work for you.
These two queries worked in my case. They are as simple as they look like but somehow I missed them our after many trials I may have miswritten them. Anyways here is the solution to my question:
db.collection.find({region:{$size:3}})
db.collection.find({ "region.2":{$exists:true}})

update array of array object elements in mongoose

I have schema data like below
{
id:'5d60fd38f6999a7792c940a4'
name:'test',
department:[
{
d_name:'Rd',
_id:'5d61092b1f234c11348eb831'
equipements:[
{
id:'5d637abd7ddd183263fa4ebc'
e_name:'first'
},
]
}
]
}
and I'm try to update the equipments by following way
College.updateOne(
{
_id: productObjectID,
'department._id': variantObjectId
},
{ $set: data }
);
but unfortunately this query is not update my equipment data .
can let me know what is right way to update. thanks
You need to search with the equipements.id in order to udpate the name
This would work
College.updateOne({
_id: productObjectID,
"department._id": variantObjectId,
"department.equipements.id": equipementId
},{ "$set": {"department.equipements.$.name": "updatedName"} });
I assume you're trying to achieve the below:
db.dummyTest.updateOne({ "_id" : ObjectId("5d63a1791b761bfc0420e590"),
"department._id": "5d61092b1f234c11348eb831",
"department.equipements._id": "5d637abd7ddd183263fa4ebc" },
{ $set: { "department.$.equipements.0.e_name.0": "Update to last" }})
MongoDB's support for updating nested arrays is poor. So you're best off avoiding their use if you need to update the data frequently
Option 1: Make department its own collection (make department, as sub document instead of array)
Option 2: Achieve it through program

Search for multiple documents in mongodb

In mongodb, is there a way I can search for multiple items at once? For example, I have a Products collection. I want to return an array of objects products where product_code = 1000, 2000. 3000.
My semi-pseudocode query would be something like:
Products.find({product_code: [1000, 2000, 3000]});
The desired output would be something like:
[
{
"_id":"1",
"product_code":"1000",
"price":"300"
},
{
"_id":"2",
"product_code":"2000",
"price":"500"
},
{
"_id":"3",
"product_code":"3000",
"price":"400"
}
]
I couldn't find anything relating to this in the documentation...
You can use the $in operator to find documents where a field contains any value in the array:
Products.find({product_code: {$in: ['1000', '2000', '3000']}});

Meteor Collection: find element in array

I have no experience with NoSQL. So, I think, if I just try to ask about the code, my question can be incorrect. Instead, let me explain my problem.
Suppose I have e-store. I have catalogs
Catalogs = new Mongo.Collection('catalogs);
and products in that catalogs
Products = new Mongo.Collection('products');
Then, people add there orders to temporary collection
Order = new Mongo.Collection();
Then, people submit their comments, phone, etc and order. I save it to collection Operations:
Operations.insert({
phone: "phone",
comment: "comment",
etc: "etc"
savedOrder: Order //<- Array, right? Or Object will be better?
});
Nice, but when i want to get stats by every product, in what Operations product have used. How can I search thru my Operations and find every operation with that product?
Or this way is bad? How real pro's made this in real world?
If I understand it well, here is a sample document as stored in your Operation collection:
{
clientRef: "john-001",
phone: "12345678",
other: "etc.",
savedOrder: {
"someMetadataAboutOrder": "...",
"lines" : [
{ qty: 1, itemRef: "XYZ001", unitPriceInCts: 1050, desc: "USB Pen Drive 8G" },
{ qty: 1, itemRef: "ABC002", unitPriceInCts: 19995, desc: "Entry level motherboard" },
]
}
},
{
clientRef: "paul-002",
phone: null,
other: "etc.",
savedOrder: {
"someMetadataAboutOrder": "...",
"lines" : [
{ qty: 3, itemRef: "XYZ001", unitPriceInCts: 950, desc: "USB Pen Drive 8G" },
]
}
},
Given that, to find all operations having item reference XYZ001 you simply have to query:
> db.operations.find({"savedOrder.lines.itemRef":"XYZ001"})
This will return the whole document. If instead you are only interested in the client reference (and operation _id), you will use a projection as an extra argument to find:
> db.operations.find({"savedOrder.lines.itemRef":"XYZ001"}, {"clientRef": 1})
{ "_id" : ObjectId("556f07b5d5f2fb3f94b8c179"), "clientRef" : "john-001" }
{ "_id" : ObjectId("556f07b5d5f2fb3f94b8c17a"), "clientRef" : "paul-002" }
If you need to perform multi-documents (incl. multi-embedded documents) operations, you should take a look at the aggregation framework:
For example, to calculate the total of an order:
> db.operations.aggregate([
{$match: { "_id" : ObjectId("556f07b5d5f2fb3f94b8c179") }},
{$unwind: "$savedOrder.lines" },
{$group: { _id: "$_id",
total: {$sum: {$multiply: ["$savedOrder.lines.qty",
"$savedOrder.lines.unitPriceInCts"]}}
}}
])
{ "_id" : ObjectId("556f07b5d5f2fb3f94b8c179"), "total" : 21045 }
I'm an eternal newbie, but since no answer is posted, I'll give it a try.
First, start by installing robomongo or a similar software, it will allow you to have a look at your collections directly in mongoDB (btw, the default port is 3001)
The way I deal with your kind of problem is by using the _id field. It is a field automatically generated by mongoDB, and you can safely use it as an ID for any item in your collections.
Your catalog collection should have a string array field called product where you find all your products collection items _id. Same thing for the operations: if an order is an array of products _id, you can do the same and store this array of products _id in your savedOrder field. Feel free to add more fields in savedOrder if necessary, e.g. you make an array of objects products with additional fields such as discount.
Concerning your queries code, I assume you will find all you need on the web as soon as you figure out what your structure is.
For example, if you have a product array in your savedorder array, you can pull it out like that:
Operations.find({_id: "your operation ID"},{"savedOrder.products":1)
Basically, you ask for all the products _id in a specific operation. If you have several savedOrders in only one operation, you can specify too the savedOrder _id, if you used the one you had in your local collection.
Operations.find({_id: "your_operation_ID", "savedOrder._id": "your_savedOrder_ID"},{"savedOrder.products":1)
ps: to bad-ass coders here, if I'm doing it wrong, please tell me.
I find an answer :) Of course, this is not a reveal for real professionals, but is a big step for me. Maybe my experience someone find useful. All magic in using correct mongo operators. Let solve this problem in pseudocode.
We have a structure like this:
Operations:
1. Operation: {
_id: <- Mongo create this unique for us
phone: "phone1",
comment: "comment1",
savedOrder: [
{
_id: <- and again
productId: <- whe should save our product ID from 'products'
name: "Banana",
quantity: 100
},
{
_id:,
productId: <- Another ID, that we should save if order
name: "apple",
quantity: 50
}
]
And if we want to know, in what Operation user take "banana", we should use mongoDB operator"elemMatch" in Mongo docs
db.getCollection('operations').find({}, {savedOrder: {$elemMatch:{productId: "f5mhs8c2pLnNNiC5v"}}});
In simple, we get documents our saved order have products with id that we want to find. I don't know is it the best way, but it works for me :) Thank you!

Best practice for obtaining embedded document metadata?

So, my schema design requires that I use an embedded document format. While I recognize that what I'm about to ask could be made easier by redesigning the schema, the current design meets all of the other requirements in place so I'm doing my best to make it work.
Consider the following rudementary schema:
{
"_id" : "01234ABCD,
"type" : "thing",
"resources" : {
foo : [
{
"herp" : "derp",
},
],
bar : [
{
"herp" : "derp",
},
{
"derp" : "herp"
}
]
},
}
Obviously the value that corresponds to the "resources" key is an embedded document. I would like to be able to efficiently calculate the count of keys in that document, and derive results based upon tests on that value. It's important to note that the length and content of the embedded doc is an unknown quantity - hence my reason for wanting to be able to query this meta. Being a complete js idiot, I've managed to cobble together the following query. For example, if I were to look for documents with more than 3 keys in the "resources" document:
db.coll.find({$where: function(){
var total = 0;
for(i in this['resources']){
++total;
if(total > 3){
return true;
}
}
}})
As I'm pretty new to Mongo and terrible at js, I feel like there may be a smarter way to do this. I'm also very curious to hear opinions on whether or not this goes against the Mongo ethos a bit by not pushing this processing to the client. Any feedback or criticism of this approach and implementation are most welcome.
Thanks for reading.
You can use an aggregate pipeline to assemble metadata about the docs and then filter on them.
db.coll.aggregate([
{$project: {
// Compute a total count of the keys in the resources docs
keys: {$add: [{$size: '$resources.foo'}, {$size: '$resources.bar'}]},
// Project the original doc
doc: '$$ROOT'
}},
// Only include the docs that have more than 3 keys
{$match: {keys: {$gt: 3}}}
])