Reputation: 4305
I have inserted document
s 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
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
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
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
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
Reputation: 36777
You need to create an instance of ObjectId
and then query using that instance, otherwise your query compares ObjectId
s 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
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