MongoDB 4.0 agrega el $convert
operador de agregación y $toString
alias que te permite hacer exactamente eso:
db.getCollection('example').aggregate([
{ "$match": { "example":1 } },
{ "$project": { "_id": { "$toString": "$_id" } } }
])
Lo más probable es que un uso principal sea utilizar el _id
valor como una "clave" en un documento.
db.getCollection('example').insertOne({ "a": 1, "b": 2 })
db.getCollection('example').aggregate([
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": [
[{
"k": { "$toString": "$_id" },
"v": {
"$arrayToObject": {
"$filter": {
"input": { "$objectToArray": "$$ROOT" },
"cond": { "$ne": ["$$this.k", "_id"] }
}
}
}
}]
]
}
}}
])
Que devolvería:
{
"5b06973e7f859c325db150fd" : { "a" : 1, "b" : 2 }
}
Lo que muestra claramente la cadena, al igual que el otro ejemplo.
En general, aunque suele haber una forma de hacer "transformaciones" en el cursor a medida que los documentos se devuelven desde el servidor. Esto suele ser algo bueno ya que un ObjectId
es una representación binaria de 12 bytes en lugar de una "cadena" hexadecimal de 24 caracteres que ocupa mucho más espacio.
El shell tiene un .map()
método
db.getCollection('example').find().map(d => Object.assign(d, { _id: d._id.valueOf() }) )
Y NodeJS tiene un Cursor.map()
que puede hacer casi lo mismo:
let cursor = db.collection('example').find()
.map(( _id, ...d }) => ({ _id: _id.toString(), ...d }));
while ( await cursor.hasNext() ) {
let doc = cursor.next();
// do something
})
Y el mismo método también existe en otros controladores (solo que no en PHP), o simplemente puede iterar el cursor y transformar el contenido, ya que es más probable que sea lo mejor que se puede hacer.
De hecho, los resultados completos del cursor se pueden reducir a un solo objeto con gran facilidad simplemente agregando a cualquier declaración de devolución del cursor, cuando se trabaja en el shell
.toArray().reduce((o,e) => {
var _id = e._id;
delete e._id;
return Object.assign(o, { [_id]: e })
},{ })
O para entornos compatibles con JavaScript ES6 completos como nodejs:
.toArray().reduce((o,({ _id, ...e })) => ({ ...o, [_id]: e }),{ })
Cosas realmente simples sin la complejidad de lo que debe procesarse en el marco de agregación. Y muy posible en cualquier idioma por los mismos medios.