sql >> Base de Datos >  >> NoSQL >> MongoDB

mongodb obtiene _id como cadena en la consulta de búsqueda

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.