Meteor collection: find element in array
I have no experience with NoSQL. So, I guess if I just try to ask about the code, my question might be wrong. Instead, let me explain my problem.
Let's say I have an e-shop. I have directories
Catalogs = new Mongo.Collection('catalogs);
and products in catalogs
Products = new Mongo.Collection('products');
Then people add orders there to the temporary collection
Order = new Mongo.Collection();
Then people submit their comments, phone number, etc. and order. I save it to a collection. Operations:
Operations.insert({
phone: "phone",
comment: "comment",
etc: "etc"
savedOrder: Order //<- Array, right? Or Object will be better?
});
It's nice, but when I want to get statistics for each product, that I used the product. How can I search through my transactions and find every transaction with this product?
Or is it bad? How did a real professional do it in the real world?
source to share
If I understand this well, here is a sample document that is stored in your collection Operation
:
{
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" },
]
}
},
Considering that to find all operations with a reference to an item, XYZ001
you just need to query:
> db.operations.find({"savedOrder.lines.itemRef":"XYZ001"})
This will return the entire document. If, instead, you are only interested in the client reference (and the _id operation), you use projection as an additional argument forfind
:
> 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 operations on multiple documents (including operations on multiple inline documents), you should take a look at the aggregation structure :
For example, to calculate the total order quantity:
> 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 }
source to share
I am a perpetual newbie, but since there is no answer, I will try.
First, start by installing robomongo or similar software that will allow you to view your collections directly in mongoDB (btw, default port is 3001)
How can I solve your problem, use the field _id
. This is an auto-generated field by mongoDB and you can safely use it as an identifier for any item in your collections.
Your collection catalog
should have a named string array field product
where you will find all the items in the product collection _id
. The same for operations: if the order is an array of products _id
, you can do the same and store that array of products _id
in the savedOrder field. Feel free to add additional fields to saveOrder if needed, eg. you create an array of objects products
with additional fields like discount
.
Regarding your request code, I am assuming that you will find everything you need on the internet once you figure out what structure you have.
For example, if you have an array of products in your savedorder array, you can pull it out like so:
Operations.find({_id: "your operation ID"},{"savedOrder.products":1)
Basically, you are requesting all products _id
in a specific operation. If you have multiple saved orders in just one operation, you can also specify saveOrder _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: for the loser codes here, if i am doing it wrong please tell me.
source to share
I find the answer :) Of course, this is not a disclosure for real professionals, but for me it's a big step. Maybe my experience was helpful. All the magic is in using the correct mango operators. 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 the user takes the "banana", we must use the mongoDB statement "elemMatch" in the Mongo docs
db.getCollection('operations').find({}, {savedOrder: {$elemMatch:{productId: "f5mhs8c2pLnNNiC5v"}}});
In simple, we receive documents, in our saved order there are products with the ID that we want to find. I don't know, this is the best way, but it works for me :) Thanks!
source to share