MongoDB 基于动态字段名称的查找值

MongoDB Lookup values based on dynamic field name

我很确定可以完成下面的操作,我正在努力了解如何在 MongoDB 中完成它。

我的数据结构如下(演示数据):

db={
  "recipes": [
    {
      "id": 1,
      "name": "flatbread pizza",
      "ingredients": {
        "1010": 1,
        "1020": 2,
        "1030": 200
      }
    },
    {
      "id": 2,
      "name": "cheese sandwich",
      "ingredients": {
        "1040": 1,
        "1050": 2
      }
    }
  ],
  "ingredients": [
    {
      "id": 1010,
      "name": "flatbread",
      "unit": "pieces"
    },
    {
      "id": 1020,
      "name": "garlic",
      "unit": "clove"
    },
    {
      "id": 1030,
      "name": "tomato sauce",
      "unit": "ml"
    },
    {
      "id": 1040,
      "name": "bread",
      "unit": "slices"
    },
    {
      "id": 1050,
      "name": "cheese",
      "unit": "slices"
    }
  ]
}

我尝试实现的输出如下所示:

  [
    {
      "id": 1,
      "name": "flatbread pizza",
      “flatbread”: “1 pieces”,
      “garlic”: “2 cloves”,
      “tomato sauce”: “200 ml”
    },
    {
      "id": 2,
      "name": "cheese sandwich",
      “bread”: “1 slices”,
      “cheese”: “2 slices”
    }
  ]

我尝试了几种方法,但我卡在了需要根据成分名称(实际上是 ID)进行查找的位置。我尝试使用 $objectToArray 将其转换为 k-v 文档,但后来我陷入了如何构建查找管道的困境。

这不是一个简单的解决方案,可能可以改进:

db.recipes.aggregate([
  {
    "$addFields": {
      ingredientsParts: {
        "$objectToArray": "$ingredients"
      }
    }
  },
  {
    $unwind: "$ingredientsParts"
  },
  {
    "$group": {
      _id: "$id",
      name: {
        $first: "$name"
      },
      ingredientsParts: {
        $push: {
          v: "$ingredientsParts.v",
          id: {
            $toInt: "$ingredientsParts.k"
          }
        }
      }
    }
  },
  {
    "$lookup": {
      "from": "ingredients",
      "localField": "ingredientsParts.id",
      "foreignField": "id",
      "as": "ingredients"
    }
  },
  {
    $unwind: "$ingredients"
  },
  {
    "$addFields": {
      "ingredientsPart": {
        "$filter": {
          input: "$ingredientsParts",
          as: "item",
          cond: {
            $eq: [
              "$$item.id",
              "$ingredients.id"
            ]
          }
        }
      }
    }
  },
  {
    $project: {
      ingredients: 1,
      ingredientsPart: {
        "$arrayElemAt": [
          "$ingredientsPart",
          0
        ]
      },
      name: 1
    }
  },
  {
    "$addFields": {
      units: {
        k: "$ingredients.name",
        v: {
          "$concat": [
            {
              $toString: "$ingredientsPart.v"
            },
            " ",
            "$ingredients.unit"
          ]
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id",
      name: {
        $first: "$name"
      },
      units: {
        $push: "$units"
      }
    }
  },
  {
    "$addFields": {
      "data": {
        "$arrayToObject": "$units"
      }
    }
  },
  {
    "$addFields": {
      "data.id": "$_id",
      "data.name": "$name"
    }
  },
  {
    "$replaceRoot": {
      "newRoot": "$data"
    }
  }
])

你可以看到它有效here

正如rickhg12hs所说,可以建模的更好