【问题标题】:How do I rename fields when performing search/projection in MongoDB?在 MongoDB 中执行搜索/投影时如何重命名字段?
【发布时间】:2014-07-10 03:58:15
【问题描述】:

是否可以重命名查找查询中返回的字段名称?我想使用$rename 之类的东西,但是我不想更改我正在访问的文档。我只想以不同的方式检索它们,类似于 SQL 中的SELECT COORINATES AS COORDS

我现在做什么:

db.tweets.findOne({}, {'level1.level2.coordinates': 1, _id:0})
{'level1': {'level2': {'coordinates': [10, 20]}}}

我想要返回的是: {'coords': [10, 20]}

【问题讨论】:

    标签: mongodb mongodb-query aggregation-framework


    【解决方案1】:

    所以基本上使用.aggregate() 而不是.find()

    db.tweets.aggregate([
        { "$project": {
            "_id": 0,
            "coords": "$level1.level2.coordinates"
        }}
    ])
    

    这会给你想要的结果。

    MongoDB 2.6 及更高版本与 find 一样返回“光标”。

    请参阅$project 和其他aggregation framework operators 了解更多详情。


    在大多数情况下,您应该在处理游标时简单地将字段重命名为从.find() 返回。以 JavaScript 为例,您可以使用.map() 来执行此操作。

    从外壳:

    db.tweets.find({},{'level1.level2.coordinates': 1, _id:0}).map( doc => {
      doc.coords = doc['level1']['level2'].coordinates;
      delete doc['level1'];
      return doc;
    })
    

    或更多内联:

    db.tweets.find({},{'level1.level2.coordinates': 1, _id:0}).map( doc => 
      ({ coords: doc['level1']['level2'].coordinates })
    )
    

    这避免了服务器上的任何额外开销,并且应该在额外处理开销超过实际减少检索数据大小的收益的情况下使用。在这种情况下(和大多数情况下),它会是最小的,因此重新处理游标结果以进行重组会更好。

    【讨论】:

      【解决方案2】:

      正如@Neil Lunn 所说,这可以通过聚合管道来实现:

      Mongo 4.2 开始,$replaceWith 聚合运算符可用于将文档替换为子文档:

      // { level1: { level2: { coordinates: [10, 20] }, b: 4 }, a: 3 }
      db.collection.aggregate(
        { $replaceWith: { coords: "$level1.level2.coordinates" } }
      )
      // { "coords" : [ 10, 20 ] }
      

      由于您提到findOne,您还可以将结果文档的数量限制为1:

      db.collection.aggregate([
        { $replaceWith: { coords: "$level1.level2.coordinates" } },
        { $limit: 1 }
      ])
      

      Mongo 4.2之前和Mongo 3.4开始,$replaceRoot可以用来代替$replaceWith

      db.collection.aggregate(
        { $replaceRoot: { newRoot: { coords: "$level1.level2.coordinates" } } }
      )
      

      【讨论】:

        【解决方案3】:

        众所周知,一般来说,$project 阶段采用字段名称并指定 1 或 0/true 或 false 以将字段包含在输出中或不包含在输出中,我们也可以针对字段指定值而不是 true 或 false重命名字段。下面是语法

            db.test_collection.aggregate([
                {$group: {
                    _id: '$field_to_group',
                    totalCount: {$sum: 1}
                }},
                {$project: {
                    _id: false,
                    renamed_field: '$_id',    // here assigning a value instead of 0 or 1 / true or false effectively renames the field.
                    totalCount: true
                }}
            ])
        

        【讨论】:

          【解决方案4】:

          阶段 (>= 4.2)

          • $addFields : {"New": "$Old"}
          • $unset : {"$Old": 1}

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-09-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-12-19
            • 2011-10-11
            相关资源
            最近更新 更多