更改Array中的属性名称

时间:2017-06-20 00:38:19

标签: mongodb mongodb-query aggregation-framework

这是聚合函数,我需要获取属于集合中每个用户的所有产品,到目前为止我已经实现了:

db.getCollection('users').aggregate([
{
  $lookup:{
   from:"products",
   localField: "id",
   foreignField: "user_id",
   as: "user_products"
  }
},
{
  $project:{
    name:1,
    user_products:{NAME:1,PRICE:1}
  }
}

])相当();

结果是:

[
{
  name:"Felipe Blanco",
  user_products:[
    {NAME:"LAPTOP",PRICE:10},
    {NAME:"CAR",PRICE:10}
  ]

}

现在我需要更改 use_products数组中对象属性的名称,如下所示:

[
{
  name:"Felipe Blanco",
  user_products:[
    {product_name:"LAPTOP",product_price:10},
    {product_name:"CAR",product_price:10}
  ]

}

1 个答案:

答案 0 :(得分:3)

这是您使用$map的地方:

db.getCollection('users').aggregate([
  { "$lookup":{
    "from": "products",
    "localField": "id",
    "foreignField": "user_id",
    "as": "user_products"
  }},
  { "$project": {
    "name": 1,
    "user_products": {
      "$map": {
        "input": "$user_products",
        "as": "up",
        "in": {
          "product_name": "$$up.NAME",
          "product_price": "$$up.PRICE" 
        }
      }
    }
  }}
])

$map运算符迭代数组并在"in"表达式中返回结果。由于这些现在是"个人成员"从数组中,您可以使用显式名称作为变量并重新分配给新的键名。

不能例如直接分配变量,如:

{ "$project": { "user_products": { "product_name": "$user_products.NAME" } }} }

因为"$user_products"引用了"数组",并且MongoDB将其解释为"指定属性的数组" ,这不是您想要什么,以及为什么要使用$map

$map的结果是:

{
        "_id" : ObjectId("594876e07011be147496f076"),
        "name" : "Felipe Blanco",
        "user_products" : [
                {
                        "product_name" : "LAPTOP",
                        "product_price" : 10
                },
                {
                        "product_name" : "CAR",
                        "product_price" : 10
                }
        ]
}

花式版

如果您不想对所有密钥进行硬编码,并且您希望使用前缀和"小写"现有的名称,然后MongoDB 3.4添加了$objectToArray$arrayToObject管道函数,允许您以更动态的方式执行此操作:

db.getCollection('users').aggregate([
  { "$lookup":{
    "from": "products",
    "localField": "id",
    "foreignField": "user_id",
    "as": "user_products"
  }},
  { "$project": {
    "name": 1,
    "user_products": {
      "$map": {
        "input": "$user_products",
        "as": "up",
        "in": {
          "$arrayToObject": {
            "$map": {
              "input": { "$objectToArray": "$$up" },
              "as": "p",
              "in": {
                "k": { "$concat": [ "product_", { "$toLower": "$$p.k" } ] },
                "v": "$$p.v"
              }
            }
          }
        }
      }
    }
  }}
])

这比简单地指定每个密钥要长得多,但如果有这样的"前缀"它确实有它的用途。是你的实际意图。