datanoise / mongo.cr

Crystal binding for MongoDB C Driver
MIT License
97 stars 35 forks source link

get id of inserted document #33

Closed sam0x17 closed 6 years ago

sam0x17 commented 6 years ago

In the comments for the collection insert method, it says: "you can retrieve the generated _id from the last_error method", however when I call the last_error method I don't see where to get the _id.

https://github.com/datanoise/mongo.cr/blob/master/src/mongo/collection.cr#L149

sam0x17 commented 6 years ago

I figured out a workaround -- if I initialize a new BSON::ObjectId object and set document["_id"] = BSON::ObjectId.new I can find out the _id before/after it gets saved. So I'm going to consider this handled.

vectorselector commented 6 years ago

it would still be nice to get a returned value, a confirmation of succesful insertion, etc... but I ended up using your trick, Sam

require("secure_random")
doc = BSON.new
doc["_id"] = SecureRandom.uuid
my-collection.insert(doc);
puts doc["_id"] #do whatever with it...

as i have legacy string _id's from a ported app (vs object id default mongo result)

sam0x17 commented 6 years ago

@vectorselector yeah I looked at the source code and didn't see an obvious way to retrieve the ID without issuing an additional query. I think this might be a limitation of the actual mongodb API, though I could be wrong.

By the way, you may want to check out the ORM I wrote (95% done) for mongo that uses this library: https://github.com/sam0x17/crystal-mongo-orm

edit: note @vectorselector that the BSON::ObjectId initializer uses the proper format for a mongo id and is probably preferable to simply using securerandom. Quoting the docs:

Returns a new ObjectId value. The 12-byte ObjectId value consists of:

a 4-byte value representing the seconds since the Unix epoch,
a 3-byte machine identifier,
a 2-byte process id, and
a 3-byte counter, starting with a random value.

This scheme is extremely resilient to collisions, so I think it might be better to use it