Earlz
Earlz

Reputation: 63805

Get _id of an inserted document in MongoDB?

say I have a product listing. When I add a new product I save it using something like

var doc=products.Insert<ProductPDO>(p);

The problem is that I want after this is done to redirect the user to the page with the product. So I need to redirect to say /products/<ObjectID>

However, I see no way of getting the ObjectID right afterwards without manually querying the database and look for a document with all the same fields and such.

Is there an easier way? (also, doc in this instance returns null for some reason)

Upvotes: 46

Views: 49311

Answers (9)

James
James

Reputation: 303

In C# your model should have an Id field attributed with [BsonId]...

internal class PersonModel
{
    [BsonId]
    public Guid Id { get; set; }
    public string FirstName { get; set; } = string.Empty;
    public string LastName { get; set; } = string.Empty;
}

In MongoDB, this will generate a _id GUID when inserting. Your insert method can use generic T, for example...

var client = new MongoClient();
var _db = client.GetDatabase(databaseName);

public void InsertRecord<T>(string collectionName, T document)
{
    var collection = _db.GetCollection<T>(collectionName);

    collection.InsertOne(document);
}

When inserting the document, the Id field will be generated by MongoDb and the model object will be updated...

var person = new PersonModel
{
    FirstName = "Peter",
    LastName = "Parker"
};
InsertRecord("Contacts", person);

Console.WriteLine($"{person.Id}");

Upvotes: 1

MX313
MX313

Reputation: 153

Class.Type as a BsonDocument not the real Class.Type can be a common cause for this issue:

e.g.:

var stream = mDB.GetCollection<vStreamMessage>(dictINI[sMONGODB_COLLECTION_NAME]);
            stream.InsertOne(msg);

Not

var stream = mDB.GetCollection<**BsonDocument**>(dictINI[sMONGODB_COLLECTION_NAME]);
            stream.InsertOne(**msg.ToBsonDocument**);

Upvotes: 0

Rodion Mostovoi
Rodion Mostovoi

Reputation: 1563

2021: If you are using MongoDb with a C#9 records, you can use this hack to get an inserted id:

private async Task<T> AddEntity<T>(T entity, string collectionName) where T: EntityBase
{
    var col = _db.GetCollection<BsonDocument>(collectionName);
    var document = entity.ToBsonDocument();
    document["_id"] = ObjectId.Empty;
    await col.InsertOneAsync(document);
    var insertedEntity = entity with
    {
        id = document["_id"].ToString()!
    };
    return insertedEntity;
}

Where EntityBase your base entity for all documents that has id field. Or just don't use generics.

Upvotes: 1

Phan Đương
Phan Đương

Reputation: 21

class BsonID
{
    [BsonId]
    public ObjectId Id { get; set; }
}
var document = new BsonDocument {
   {"_id", new BsonID().Id },
   { "code", dr.Cells["code"].Value.ToString() },
   { "name", dr.Cells["name"].Value.ToString() },
  };
var customers = _database.GetCollection<BsonDocument>("Customers");
customers.InsertOne(document);
var id = document.ElementAt(0).Value.ToString();

Upvotes: 2

h-rai
h-rai

Reputation: 3964

I'm converting the custom type T to BsonDocument before persisting it.

var bsonDocument = item.ToBsonDocument();
_mongoCollection.InsertOne(bsonDocument);

T has a property Id:

[BsonId]
public ObjectId Id { get; set; }

When I call ToBsonDocument(), the Id field gets populated with ObjectId which gets pushed to Mongo DB.

It creates the Id itself in the code instead of delegating to Mongo DB to create it. But it suffices my case.

Upvotes: 2

Scott Hernandez
Scott Hernandez

Reputation: 7590

The Insert method automatically sets the property that is declared as the BSON ID of the model.

If declared as follows...

[BsonId]
public ObjectId Id { get; set; }

... then the Id field will contain the default (new, unique) BSON ID of the object after inserting the object into a collection:

coll.Insert(obj);
// obj.Id is now the BSON ID of the object

Upvotes: 78

CodingYourLife
CodingYourLife

Reputation: 8588

If you know the type of ID you can do something like this:

public static TId GetId<TId>(this BsonDocument document) where TId : struct
{
    if (document == default(BsonDocument))
    {
        throw new ArgumentNullException("document");
    }

    var id = document["_id"];

    object idAsObject;

    if (id.IsGuid)
    {
        idAsObject = (object)id.AsGuid;
    }
    else if (id.IsObjectId)
    {
        idAsObject = (object)id.AsObjectId;
    }
    else
    {
        throw new NotImplementedException(string.Format("Unknown _id type \"{0}\"", id.BsonType));
    }

    var idCasted = (TId)idAsObject;

    return idCasted;
}

Use it like this:

Guid idOfDoc = myBsonDocument.GetId<Guid>();

Still you should prefere have a dedicated property as in the chosen answer...

Upvotes: 3

Jorge Barraza Z
Jorge Barraza Z

Reputation: 191

As the comment above, add the fild ID in your model with

[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string id { get; set; }

using:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

and then when you insert the object, mongo return the ID of the document into the fild ID of the model.

Upvotes: 7

Shaheen Ghiassy
Shaheen Ghiassy

Reputation: 7517

When you insert an object into the mongodb, mongo will update the object with the internal ID.

So if

data = {
  title: "Howdy"
}

Then when we insert the data object into the db

db.collection('collectionName', function(err, collection) {
  collection.insert(data);
  console.log(data._id); // <- The mongodb id is now set on the item
});

Upvotes: 22

Related Questions