MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

mongodb obtém _id como string na consulta de localização


O MongoDB 4.0 adiciona o $convert operador de agregação e o $toString alias que permite que você faça exatamente isso:
db.getCollection('example').aggregate([
  { "$match": { "example":1 } },
  { "$project": { "_id": { "$toString": "$_id" } } }
])

Um uso principal provavelmente seria usar o _id valor como uma "chave" em um 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 retornaria:
{ 
  "5b06973e7f859c325db150fd" : { "a" : 1, "b" : 2 }
}

O que mostra claramente a string, assim como o outro exemplo.

Geralmente, porém, geralmente há uma maneira de fazer "transformações" no cursor à medida que os documentos são retornados do servidor. Isso geralmente é uma coisa boa, pois um ObjectId é uma representação binária de 12 bytes em oposição a uma "string" hexadecimal de 24 caracteres que ocupa muito mais espaço.

O shell tem um .map() método
db.getCollection('example').find().map(d => Object.assign(d, { _id: d._id.valueOf() }) )

E o NodeJS tem um Cursor.map() que pode fazer a mesma coisa:
let cursor = db.collection('example').find()
    .map(( _id, ...d }) => ({ _id: _id.toString(), ...d }));

while ( await cursor.hasNext() ) {
  let doc = cursor.next();
  // do something
})

E o mesmo método também existe em outros drivers ( mas não no PHP ), ou você pode apenas iterar o cursor e transformar o conteúdo como é mais provável que seja a melhor coisa a fazer.

Na verdade, os resultados inteiros do cursor podem ser reduzidos em um único objeto com grande facilidade, simplesmente adicionando a qualquer instrução de retorno do cursor, ao trabalhar no shell
.toArray().reduce((o,e) => { 
  var _id = e._id;
  delete e._id;
  return Object.assign(o, { [_id]: e })
},{ })

Ou para ambientes completos de suporte a JavaScript ES6, como nodejs:
.toArray().reduce((o,({ _id, ...e })) =>  ({ ...o, [_id]: e }),{ })

Coisas realmente simples sem a complexidade do que precisa ser processado na estrutura de agregação. E muito possível em qualquer idioma pelos mesmos meios.