简体   繁体   English

Mongodb聚合或投影

[英]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 从应用程序中的数据库中提取Parcel使用的所有项目
  2. perform all computations on database side using aggregation (and $lookup ) 使用聚合(和$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. 如果您当前的数据集很小(例如100 Mb),请选择您喜欢的方式-两者都将非常有用。

Update 更新

Since you need to distribute Orders to Parcels I'd prefer to go with option #1, though using aggregation is still possible. 由于您需要将Orders分发到Parcels我仍然希望选择选项1,尽管仍然可以使用汇总。

This is what I would do: 这就是我要做的:

  1. pull an Order from database 从数据库中提取Order
  2. pull all related Items from database by ids found in Order.items 通过在Order.items找到的ID从数据库中提取所有相关Items
  3. perform calculation of Order weight 执行Order重量的计算
  4. create one Parcel if weight < 30 and save it to database 如果重量<30,则创建一个Parcel ,并将其保存到数据库中
  5. or if weight > 30 distribute somehow Items to Parcels and save them to database 或者如果重量> 30, Parcels某种方式将Items分发到Parcels并将其保存到数据库

Note, that you can pull multiple Items by their ids in one call with query like this: 请注意,您可以在一个调用中通过如下查询通过其ID提取多个Items

{
 _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. 请注意MongoDB没有事务或多文档原子性这一事实。 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 您可以使用以下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" }
  }}
])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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