MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

mongodb obtient _id en tant que chaîne dans la requête de recherche

MongoDB 4.0 ajoute le $convert l'opérateur d'agrégation et le $toString alias qui vous permet de faire exactement cela :

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

Une utilisation principale serait très probablement d'utiliser le _id valeur en tant que "clé" dans un document.

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"] }
              }
            }
          }
        }] 
      ]
    }
  }}
])

Ce qui renverrait :

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

Ce qui montre clairement la chaîne, comme le fait l'autre exemple.

Généralement, bien qu'il existe généralement un moyen de faire des "transformations" sur le curseur lorsque les documents sont renvoyés par le serveur. C'est généralement une bonne chose puisqu'un ObjectId est une représentation binaire de 12 octets par opposition à une "chaîne" hexadécimale de 24 caractères qui prend beaucoup plus d'espace.

Le shell a un .map() méthode

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

Et NodeJS a un Cursor.map() qui peut faire à peu près la même chose :

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

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

Et la même méthode existe également dans d'autres pilotes (mais pas PHP), ou vous pouvez simplement itérer le curseur et transformer le contenu, ce qui est probablement la meilleure chose à faire.

En fait, les résultats de curseur entiers peuvent être réduits en un seul objet avec une grande facilité en ajoutant simplement à n'importe quelle instruction de retour de curseur, lorsque vous travaillez dans le shell

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

Ou pour les environnements complets prenant en charge JavaScript ES6 comme nodejs :

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

Des choses vraiment simples sans la complexité de ce qui doit être traité dans le cadre d'agrégation. Et très possible dans n'importe quelle langue par à peu près les mêmes moyens.