MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

mongodb erhält _id als Zeichenfolge in der Suchabfrage

MongoDB 4.0 fügt den $convert hinzu Aggregationsoperator und der $toString Alias, mit dem Sie genau das tun können:

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

Eine Hauptverwendung wäre jedoch höchstwahrscheinlich die Verwendung der _id Wert als "Schlüssel" in einem Dokument.

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

Was zurückgeben würde:

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

Was den String deutlich zeigt, ebenso wie das andere Beispiel.

Im Allgemeinen gibt es jedoch normalerweise eine Möglichkeit, "Transformationen" am Cursor durchzuführen, wenn Dokumente vom Server zurückgegeben werden. Dies ist normalerweise eine gute Sache, da eine ObjectId ist eine 12-Byte-Binärdarstellung im Gegensatz zu einer 24-stelligen hexadezimalen "Zeichenfolge", die viel mehr Platz benötigt.

Die Shell hat eine .map() Methode

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

Und NodeJS hat eine Cursor.map() die fast dasselbe tun können:

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

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

Und die gleiche Methode gibt es auch in anderen Treibern ( nur nicht in PHP ), oder Sie können einfach den Cursor durchlaufen und den Inhalt transformieren, wie es wahrscheinlicher am besten ist.

Tatsächlich können ganze Cursor-Ergebnisse mit großer Leichtigkeit in ein einziges Objekt reduziert werden, indem einfach eine beliebige Cursor-Rückgabeanweisung hinzugefügt wird, wenn in der Shell gearbeitet wird

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

Oder für Umgebungen mit voller ES6-JavaScript-Unterstützung wie nodejs:

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

Wirklich einfaches Zeug ohne die Komplexität dessen, was im Aggregationsframework verarbeitet werden muss. Und sehr wahrscheinlich in jeder Sprache auf die gleiche Weise.