36

I have inserted documents into MongoDB without an id. And I want to retrieve them by searching through their MongoDB ObjectId, that has been assigned in default.

Here is my attempt-

var query_id = Query.EQ("_id", "50ed4e7d5baffd13a44d0153");
var entity = dbCollection.FindOne(query_id);
return entity.ToString();

And I get following error-

A first chance exception of type 'System.NullReferenceException' occurred

What is the problem?

6 Answers 6

69

You need to create an instance of ObjectId and then query using that instance, otherwise your query compares ObjectIds to string and fails to find matching documents.

This should work:

var query_id = Query.EQ("_id", ObjectId.Parse("50ed4e7d5baffd13a44d0153"));
var entity = dbCollection.FindOne(query_id);
return entity.ToString();
Sign up to request clarification or add additional context in comments.

3 Comments

This answer is nearly correct. At least in C#, it appears that there is no longer a FindOne() method. Replace it with FindOneAs() instead. Here's a link to a good example, this one uses FindAs(), but it's the same principle: stackoverflow.com/a/12345580/2705003
There is now no longer a FineAs or FindOneAs method, Minhas Kamal answer should be referenced instead
As soul-check mentions. The _id field is NOT a string, but a more complex datatype called ObjectId.
40

In C# for latest official MongoDB.Driver write this-

var filter_id = Builders<MODEL_NAME>.Filter.Eq("id", ObjectId.Parse("50ed4e7d5baffd13a44d0153"));
var entity = dbCollection.Find(filter).FirstOrDefault();
return entity.ToString();

We can accomplish the same result without converting id from string to ObjectId. But then, we will have to add [BsonRepresentation(BsonType.ObjectId)] before id attribute in the model class.

The code can even be further simplified using lambda expression-

var entity = dbCollection.Find(document => document.id == "50ed4e7d5baffd13a44d0153").FirstOrDefault();
return entity.ToString();

3 Comments

Upon ObjectId.Parse(cool_id.ToString()) I continually get that the guid is "not a valid 24 digit hex string" - what an I doing wrong?
@VincentBuscarello, as it says, your cool_id has not valid string representation. Might be use of ObjectId.TryParse(cool_id.ToString(), out ObjectId parsedResult) instead?
@minhas-kamal can you help me on my query above soln not works in my case stackoverflow.com/questions/74835380/…
4

If you're here in 2018 and want copy/paste code that still works or pure string syntax;

    [Fact]
    public async Task QueryUsingObjectId()
    {
        var filter = Builders<CosmosParkingFactory>.Filter.Eq("_id", new ObjectId("5b57516fd16cb04bfc35fcc6"));
        var entity = stocksCollection.Find(filter);
        var stock = await entity.SingleOrDefaultAsync();
        Assert.NotNull(stock);

        var idString = "5b57516fd16cb04bfc35fcc6";
        var stringFilter = "{ _id: ObjectId('" + idString + "') }";
        var entityStringFiltered = stocksCollection.Find(stringFilter);
        var stockStringFiltered = await entityStringFiltered.SingleOrDefaultAsync();
        Assert.NotNull(stockStringFiltered);
    }

Comments

3

The selected answer is correct. For anyone confused by the Query.EQ, here is another way to write a basic update (updates the entire mongodb document):

string mongoDocumentID = "123455666767778";
var query = new QueryDocument("_id", ObjectId.Parse(mongoDocumentID)); 
var update = new UpdateDocument { { "$set", documentToSave } };
mongoCollection.Update(query, update, UpdateFlags.Multi);

The ObjectId object is needed when you want to actually search by object ID, otherwise it is comparing string to objectid type, and it won't match. Mongo is very type-strict in this way, regardless if the field name is correct.

Comments

0

You can also do it this way, its

public static ObjectId GetInternalId(string id)
    {
        if (!ObjectId.TryParse(id, out ObjectId internalId))
            internalId = ObjectId.Empty;

        return internalId;
    }

then in your method you can do something like this

ObjectId internalId = GetMongoId.GetInternalId(id);
        return await YourContext.YourTable.Find(c => c.InternalId == internalId).FirstOrDefaultAsync();

Note: id param in GetInternalId its a parameter on that method. In case you need as this:

public async Task<YourTable> Find(string id)
    {
        ObjectId internalId = GetMongoId.GetInternalId(id);
        return await YourContext.YourTable.Find(c => c.InternalId == internalId).FirstOrDefaultAsync();
    }

Hope it helps also.

Comments

0

With the MongoDB.Driver 2.23.1 and dotnet 6.0

// Example schema
public class NoteTags
{
    [GraphQLIgnore]
    [BsonId]
    public ObjectId Id { get; set; }

    [BsonElement("name")]
    public string Name { get; set; }
}

Mongo db query with _id

using MongoDB.Bson;
using MongoDB.Driver;

class SampleQueryByID {
  public GetTags() {
    var client = new MongoClient( /** Mongo Settings */ );
    var db = client.GetDatabase("db");
    var tagsCollection = db.GetCollection < NoteTags > ("tags");

    var findOptions = new FindOptions {
      BatchSize = 10
    };
    FilterDefinition < NoteTags > filter; = Builders < NoteTags > .Filter.In(
      "_id",
      TagsIds.Select(tag => ObjectId.Parse(tag)) // Very important to parse
    );

    // res variable to hold the mongo db query result
    var res = new List < NoteTags > ();

    // use the above filter and filter option
    using(var cursor = tagsCollection.Find(filter, findOptions).ToCursor()) {
      if (cursor.MoveNext()) {
        var d = cursor.Current.ToList();

        for (int i = 0; i < d.Count; i++) {
          res.Add(d[i]);
        }
      }
    }
  }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.