48

Is there an operator I could use in aggregate function to get a string instead of ObjectId in response?

db.something.aggregate([
  { "$match": { "property": { "$exists": true } } },
  { "$project": { "stringId": "$_id.???" } }
])
Ashh
  • 44,693
  • 14
  • 105
  • 132
matus
  • 1,483
  • 4
  • 16
  • 19
  • 2
    No there isn't. The aggregation framework does not re-cast any data types ( except to string from numeric via `$substr` and numeric to Date or Date to numeric is basically possible with trickery ). Why would you think this is needed anyway? It's fairly simple in most languages to write the `ObjectId` value as a string anyway. – Blakes Seven Mar 17 '16 at 12:04
  • 2
    @BlakesSeven There is always why :) Because of simplicity. Of course you can post process it. But it would be nice if I could just pass the result to other service/party who requires plain string. ... – matus Mar 17 '16 at 12:16
  • 1
    Well like I said, with most languages the BSON is just cast to local types. And for "most" languages, there is no work at all required to simply output as a string. Personally I prefer the extended JSON output form i.e `{ "$oid": "56ea9e8bb1e015d13b376db5" }` since at least that lets a remote client know that the data is indeed an `ObjectId` so it can parse and cast correctly itself. That's a good thing, especially considering that storage is **half** the bytes of the string length. – Blakes Seven Mar 17 '16 at 12:32

3 Answers3

91

Mongodb 4.0 has introduced $toString aggregation operator. So, Now you can easily convert ObjectId to string

db.collection.aggregate([
  {
    $project: {
      _id: {
        $toString: "$_id"
      }
    }
  }
])

OR vice versa using $toObjectId aggregation

db.collection.aggregate([
  {
    $project: {
      _id: {
        $toObjectId: "$_id"
      }
    }
  }
])
Ashh
  • 44,693
  • 14
  • 105
  • 132
11

There is no Direct Operator in aggregate function to get String from ObjectId.

After version 2.6 You can use ObjectId.toString() method to convert your ObjectId to string. First you match and project your ObjectID. Then you can convert this object ID to string by using ObjectID.toString().

db.something.aggregate([{"$match":{'property': {$exists:true}}},{"$project":{"_id":1}}]) 

And then use resulting Object and get the string as response using ObjectID.tostring()

Edit: You can access the str attribute of the object id using

ObjectId("507f191e810c19729de860ea").str

source: mongodb docs

Tamil Arasi
  • 179
  • 5
-17

You can do it inline using the $concat operator:

db.something.aggregate(
    [
        { $match :
            { 'property' :
                { $exists:true }
            }
        },
        { $project:
            { stringId:
                { $concat: [ ObjectId().str ] }
            }
        }
    ]
)
Matt Clark
  • 27,671
  • 19
  • 68
  • 123
  • 1
    For me, this doesn't make "stringId" the ObjectId of the record. It makes it a stringified version of a brand new ObjectId. In particular, it's the same value for all the documents returned. So I don't think this is right. – mcdave Oct 26 '16 at 17:29
  • lol fail ...... – Nicholas Hamilton Aug 20 '22 at 22:01