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?

+3


source to share


3 answers


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 }

      

+6


source


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.

+1


source


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!

0


source







All Articles