MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

mongodb ottieni _id come stringa nella query di ricerca

MongoDB 4.0 aggiunge il $convert operatore di aggregazione e $toString alias che ti permette di fare esattamente questo:

db.getCollection('example').aggregate([
  { "$match": { "example":1 } },
  { "$project": { "_id": { "$toString": "$_id" } } }
])

Un utilizzo principale sarebbe molto probabilmente quello di utilizzare _id valore come "chiave" in 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"] }
              }
            }
          }
        }] 
      ]
    }
  }}
])

Che ritornerebbe:

{ 
  "5b06973e7f859c325db150fd" : { "a" : 1, "b" : 2 }
}

Che mostra chiaramente la stringa, come fa l'altro esempio.

In genere, tuttavia, di solito esiste un modo per eseguire "trasformazioni" sul cursore poiché i documenti vengono restituiti dal server. Questa è solitamente una buona cosa poiché un ObjectId è una rappresentazione binaria di 12 byte invece di una "stringa" esadecimale di 24 caratteri che occupa molto più spazio.

La shell ha un .map() metodo

db.getCollection('example').find().map(d => Object.assign(d, { _id: d._id.valueOf() }) )

E NodeJS ha un Cursor.map() che può fare più o meno la stessa cosa:

let cursor = db.collection('example').find()
    .map(( _id, ...d }) => ({ _id: _id.toString(), ...d }));

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

E lo stesso metodo esiste anche in altri driver (solo non PHP), oppure puoi semplicemente scorrere il cursore e trasformare il contenuto come è più probabile che sia la cosa migliore da fare.

In effetti, i risultati dell'intero cursore possono essere ridotti in un unico oggetto con grande facilità semplicemente aggiungendo a qualsiasi istruzione di ritorno del cursore, quando si lavora nella shell

.toArray().reduce((o,e) => { 
  var _id = e._id;
  delete e._id;
  return Object.assign(o, { [_id]: e })
},{ })

O per ambienti che supportano JavaScript ES6 completi come nodejs:

.toArray().reduce((o,({ _id, ...e })) =>  ({ ...o, [_id]: e }),{ })

Roba davvero semplice senza la complessità di ciò che deve elaborare nel framework di aggregazione. E molto possibile in qualsiasi lingua con gli stessi mezzi.