Mike Barnes
Mike Barnes

Reputation: 4305

Query MongoDB Using 'ObjectId'

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?

Upvotes: 36

Views: 61960

Answers (6)

Vipul Dessai
Vipul Dessai

Reputation: 320

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]);
        }
      }
    }
  }
}

Upvotes: 0

Raul Baez
Raul Baez

Reputation: 1

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.

Upvotes: 0

Kdog
Kdog

Reputation: 296

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);
    }

Upvotes: 4

Minhas Kamal
Minhas Kamal

Reputation: 22206

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();

Upvotes: 40

soulcheck
soulcheck

Reputation: 36777

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();

Upvotes: 69

smakus
smakus

Reputation: 1437

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.

Upvotes: 3

Related Questions