Mongodb聚合或投影

时间:2018-12-18 13:05:30

标签: node.js mongodb mongodb-query aggregation-framework

findHeight

我有这种模型结构。我想计算每个订单的重量。 我应该使用聚合还是有人有任何想法?

这是订单的示例:

{
  "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"
    }
  ]
}

enter image description here

2 个答案:

答案 0 :(得分:1)

在这里您有两个选择,而无需更改模型结构:

  1. 从应用程序数据库中提取Parcel中使用的所有项目
  2. 使用聚合(和$lookup)在数据库端执行所有计算

这非常取决于您的实际数据模型和数据集大小。第一种选择非常简单明了,在大型数据集上可能表现得更好,尤其是在涉及分片/副本集时。但是它需要更多的数据库往返,这将带来更多的延迟。另一方面,在某些情况下,聚合在查找时可能会非常慢。 但是唯一的好方法是对您的真实数据进行测试。如果您当前的数据集很小(例如100 Mb),请选择您喜欢的方式-两者都将非常有用。

更新

由于您需要将Orders分发到Parcels,因此我仍然希望使用选项#1,尽管仍然可以使用聚合。

这就是我要做的:

  1. 从数据库中提取一个Order
  2. 通过Items中找到的ID从数据库中提取所有相关的Order.items
  3. 执行Order权重的计算
  4. 如果权重<30,则创建一个Parcel并将其保存到数据库
  5. 或者如果权重> 30,则以某种方式将Items分配到Parcels并将其保存到数据库中

请注意,您可以在一个调用中通过如下查询通过其Items的ID拉取多个{ _id: { $in: [<id1>, <id2>] } }

{{1}}

还有另外一件事要考虑。请注意MongoDB没有事务或多文档原子性这一事实。因此,使用模式定义的显示方式执行这种类型的操作(从数据库中抽取内容,执行计算并存储回去)会导致创建重复项。

答案 1 :(得分:1)

您可以在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" }
  }}
])