在投影中将子字段提升到顶层而不列出所有键 [英] Promote subfields to top level in projection without listing all keys

查看:16
本文介绍了在投影中将子字段提升到顶层而不列出所有键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有像 {'a': 1, 'z': {'b': 2, 'c': 3,}} 这样的文件.

I have documents like {'a': 1, 'z': {'b': 2, 'c': 3,}}.

我想要 {'a': 1, 'b': 2, 'c': 3}.

我可以用

aggregate({'$project': {'b': '$z.b', 'c': '$z.c'}})

是否可以在不手动列出子文档中的所有键的情况下做到这一点?

Is it possible to do it without listing all of the keys in the subdocument manually?

推荐答案

在 MongoDB 3.4 中,您可以使用 $objectToArray$arrayToObject$replaceRoot为了改变这个:

With MongoDB 3.4 you can use $objectToArray and $arrayToObject with $replaceRoot in order to change this:

db.wish.aggregate([
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": {
        "$concatArrays": [
          [{ "k": "a", "v": "$a" }],
          { "$objectToArray": "$z" }
        ]
      }
    }
  }}
])

甚至连这么长的咒语都没有指定 "a" 属性:

Or even this long incantation without even specifying the "a" property:

db.wish.aggregate([
  { "$replaceRoot": {
    "newRoot": {
      "$arrayToObject": {
        "$reduce": {
          "input": {
            "$filter": {
              "input": { "$objectToArray": "$$ROOT" },
              "as": "r",
              "cond": { "$ne": [ "$$r.k", "_id" ] }
            }
          },
          "initialValue": [],
          "in": {
            "$concatArrays": [
              "$$value",
              { "$cond": {
                "if": {  "$gt": [ "$$this.v", {} ] },
                "then": { "$objectToArray": "$$this.v" },
                "else": ["$$this"]
              }}
            ]
          }  
        } 
      }
    }
  }}
])  

两者都产生:

{ "a" : 1, "b" : 2, "c" : 3 }

$concatArrays 的有趣用法在未来的版本中应该是不必要的,因为将会有一个 $mergeObjects 操作符,这会使它更简洁一些.

The funny use of $concatArrays should not be necessary in future versions since there will be a $mergeObjects operator which will make that a bit cleaner.

但您基本上可以非常简单地在客户端代码中执行相同的操作.例如在 JavaScript 中的 shell:

But you can basically just do the same thing in client code pretty simply. For example in JavaScript for the shell:

db.wish.find().map( doc => (
  Object.assign({ a: doc.a }, doc.z )
))

或者是没有"a"的版本:

db.wish.find().map( doc => 
  Object.keys(doc).filter(k => k !== '_id').map(k => 
   ( typeof(doc[k]) === "object" ) ? 
     Object.keys(doc[k]).map(i => ({ [i]: doc[k][i] }))
       .reduce((acc, curr) => Object.assign(acc,curr),{})
     : { [k]: doc[k] }
  ).reduce((acc,curr) => Object.assign(acc,curr),{})
)

产生相同的输出

{ "a" : 1, "b" : 2, "c" : 3 }

这篇关于在投影中将子字段提升到顶层而不列出所有键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆