简体   繁体   中英

Mongodb aggregation or projection

 { "items": [ { "id": "5bb619e49593e5d3cbaa0b52", "name": "Flowers", "weight": "1.5" }, { "id": "5bb619e4ebdccb9218aa9dcb", "name": "Chair", "weight": "8.4" }, { "id": "5bb619e4911037797edae511", "name": "TV", "weight": "20.8" }, { "id": "5bb619e4504f248e1be543d3", "name": "Skateboard", "weight": "5.9" }, { "id": "5bb619e40fee29e3aaf09759", "name": "Donald Trump statue", "weight": "18.4" }, { "id": "5bb619e44251009d72e458b9", "name": "Molkkÿ game", "weight": "17.9" }, { "id": "5bb619e439d3e99e2e25848d", "name": "Helmet", "weight": "22.7" } ] } 

I have this structure of models. I want to calculate the weight of each order. Should I use aggregation or does someone have any idea?

this is an example of order :

{
      "id": "5bb61dfd4d64747dd8d7d6cf",
      "date": "Sat Aug 11 2018 02:01:25 GMT+0000 (UTC)",
      "items": [
        {
          "item_id": "5bb619e44251009d72e458b9",
          "quantity": 4
        },
        {
          "item_id": "5bb619e4504f248e1be543d3",
          "quantity": 2
        },
        {
          "item_id": "5bb619e40fee29e3aaf09759",
          "quantity": 3
        }
      ]
    }

在此处输入图片说明

You have two options here without changing your model structure:

  1. pull all items used in Parcel from database in your application
  2. perform all computations on database side using aggregation (and $lookup )

It very depends on your actual data model and dataset size. First option is very straightforward and potentially can be more performant on big datasets especially when sharding/replica set involved. But it requires more roundtrips to database which will bring more latency. On the other hand aggregation in certain cases can be quite slow on lookups. But the only good way is to test it on your real data. If your current dataset is tiny (say 100s of Mb) choose the way you comfortable with - both will work great.

Update

Since you need to distribute Orders to Parcels I'd prefer to go with option #1, though using aggregation is still possible.

This is what I would do:

  1. pull an Order from database
  2. pull all related Items from database by ids found in Order.items
  3. perform calculation of Order weight
  4. create one Parcel if weight < 30 and save it to database
  5. or if weight > 30 distribute somehow Items to Parcels and save them to database

Note, that you can pull multiple Items by their ids in one call with query like this:

{
 _id: { $in: [<id1>, <id2>] }
}

There is also one more thing to consider. Please pay attention to the fact that MongoDB do not have transactions or multidocument atomicity. So performing this type of operations (pulling something from DB, performing calculations, and storing back) with schema defined the way you show can lead to creating duplicates.

You can use below aggregation

db.order.aggregate([
  { "$unwind": "$items" },
  { "$lookup": {
    "from": "items",
    "localField": "items.item_id",
    "foreignField": "id",
    "as": "item"
  }},
  { "$unwind": "$item" },
  { "$addFields": { "items.weight": "$item.weight" }},
  { "$group": {
    "_id": "$_id",
    "items": { "$push": "$items" },
    "date": { "$first": "$date" }
  }}
])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM