web-dev-qa-db-ja.com

MongoDBで検索/投影を実行するときにフィールドの名前を変更するにはどうすればよいですか?

検索クエリで返されるフィールドの名前を変更することは可能ですか? $renameのようなものを使用したいのですが、アクセスしているドキュメントを変更したくありません。 SQLでSELECT COORINATES AS COORDSのように機能する別の方法で取得したいだけです。

私が今していること:

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

返されたいのは:{'coords': [10, 20]}

36
themiurgo

そのため、基本的には .aggregate() の代わりに を使用します.find()

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

そして、それはあなたが望む結果を与えます。

MongoDB 2.6以降のバージョンは、findと同様に「カーソル」を返します。

_$project_ およびその他の 集約フレームワーク演算子 を参照してください。


ほとんどの場合、カーソルの処理時に.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 })
)
_

これにより、サーバーでの追加のオーバーヘッドが回避され、追加の処理オーバーヘッドが、取得されるデータのサイズの実際の縮小の利益を上回るような場合に使用する必要があります。この場合(そしてほとんどの場合)、最小限に抑えられるため、カーソルの結果を再処理して再構築する方が適切です。

45
Neil Lunn

@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" } } }
)
2
Xavier Guihot