MongoDB: automatically generated IDs are zeroes

19,867

Solution 1

Use BsonId attribute:

public class Address
{
    [BsonId]
    public string _id { get; set; }
    public string Street { get; set; }
    public string House { get; set; }
}

Identifying the Id field or property

To identify which field or property of a class is the Id you can write:

public class MyClass {
    [BsonId]
    public string SomeProperty { get; set; }
}

Driver Tutorial

Edit

It's actually not working. I will check later why. If you need get it work use following:

    [Test]
   public void Test()
    {
        var collection = Read.Database.GetCollection("test");

        var user = new User
        {
            Name = "Sam",
            Addresses = (new Address[] { new Address { House = "BIGHOUSE", Street = "BIGSTREET", _id = ObjectId.GenerateNewId().ToString() } })
        };

        collection.Insert(user.ToBsonDocument());
    }

Solution 2

It's not so much a bug as a case of unmet expectations. Only the top level _id is automatically assigned a value. Any embedded _ids should be assigned values by the client code (use ObjectId.GenerateNewId). It's also possible that you don't even need an ObjectId in the Address class (what is the purpose of it?).

Solution 3

Get the collection as User type:

var collection = db.GetCollection<User>("users");

Initialize the field _id as follows:

var user = new User
{
   _id = ObjectId.Empty,
   Name = "Sam",
   Addresses = (new Address[] { new Address { House = "BIGHOUSE", Street = "BIGSTREET" } })
};

Then you insert the object:

collection.InsertOne(user);

The _id field will automatically be generated.

In this link you will find alternative ways to have customized auto-generated ID(s).

Share:
19,867
Alex
Author by

Alex

Updated on July 13, 2022

Comments

  • Alex
    Alex almost 2 years

    I'm using MongoDB and official C# driver 0.9

    I'm just checking how embedding simple documents works.

    There are 2 easy classes:

    public class User
    {
        public ObjectId _id { get; set; }
        public string Name { get; set; }
        public IEnumerable<Address> Addresses { get;set; }
    }
    
    public class Address
    {
        public ObjectId _id { get; set; }
        public string Street { get; set; }
        public string House { get; set; }
    }
    

    I create a new user:

    var user = new User
    {
        Name = "Sam",
        Addresses = (new Address[] { new Address { House = "BIGHOUSE", Street = "BIGSTREET" } })
    };
    
    collection.Insert(user.ToBsonDocument());
    

    The user is successfully saved, so is his address.

    After typing

    db.users.find()
    

    in MongoDB shell, I got the following result:

    { "_id" : ObjectId("4e572f2a3a6c471d3868b81d"), "Name" : "Sam",  "Addresses" : [
            {
                    "_id" : ObjectId("000000000000000000000000"),
                    "Street" : "BIGSTREET",
                    "House" : "BIGHOUSE"
            }
    ] }
    

    Why is address' object id 0?

    Doing queries with the address works though:

    collection.FindOne(Query.EQ("Addresses.Street", streetName));
    

    It returns the user "Sam".

  • Alex
    Alex over 13 years
    Ok, I submitted it. Thanks for the solution with ObjectId.GenerateNewId(), I placed it in the constructor for all Document classes, and it works now.
  • Alex
    Alex over 13 years
    Oh, I always thought that ObjectIds are mandatory for all documents. If it's okay to have no id it all, then it's great. I wouldn't call it unmet expectations, because, for example, Ruby driver creates IDs for embedded documents.
  • UpTheCreek
    UpTheCreek over 12 years
    Is this documented somewhere? I haven't seen any mention of it. What is the rationale behind autoassigning the root, but not emdeded docs (I thought they were all 'documents')?
  • UpTheCreek
    UpTheCreek over 12 years
    Also, any way of using the Comb GUID generator in this way?
  • David Mårtensson
    David Mårtensson about 12 years
    @UpTheCreek, Only the root document is indexed in the default index for the collection so only the root document requires an unique id.
  • Alexus1024
    Alexus1024 over 7 years
    there is also attribute [BsonId(IdGenerator = typeof(ObjectIdGenerator))]
  • stratovarius
    stratovarius over 7 years
    Dont always think of ObjectID as just a legacy ID. It is a complex type which also has Timestamp, CreationDate and some other valuable properties. So dev may have some 'side' purposes while using it.
  • Dan
    Dan almost 6 years
    Tried this but it also does not work. Always get zeros. Also tried to combine this with the other suggestions above.
  • Paddymac
    Paddymac over 4 years
    Upvote for ObjectId.GenerateNewId().ToString(); Thanks!