使用'ObjectId'查询MongoDB

35

我已经将document插入MongoDB,但没有id。 我想通过搜索它们的MongoDB ObjectId来检索它们,这个ObjectId默认赋值的

这是我的尝试-

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

我遇到了以下错误-

发生了“System.NullReferenceException”类型的第一次机会异常

问题出在哪里?

5个回答

67
你需要创建一个 ObjectId 实例,然后使用该实例进行查询,否则你的查询将会把 ObjectId 与字符串进行比较,从而无法找到匹配的文档。
这个应该可以工作:
var query_id = Query.EQ("_id", ObjectId.Parse("50ed4e7d5baffd13a44d0153"));
var entity = dbCollection.FindOne(query_id);
return entity.ToString();

4
这个答案几乎正确。至少在 C# 中,似乎不再有 FindOne() 方法。请改用 FindOneAs()。这里有一个好的例子链接,它使用了 FindAs(),但原理相同:https://dev59.com/22jWa4cB1Zd3GeqPojgY#12345580 - kbpontius
4
现在没有FineAs或FindOneAs方法,应参考Minhas Kamal的答案。 - Brian Ogden
正如 soul-check 所提到的,_id 字段不是字符串,而是一种更复杂的数据类型,称为 ObjectId。 - FlyingV

37

在最新的官方MongoDB.Driver中使用C#编写:

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

我们不需要将id从字符串转换为ObjectId,也可以获得相同的结果。但是,我们需要在模型类中的id属性之前添加[BsonRepresentation(BsonType.ObjectId)]

使用lambda表达式可以进一步简化代码-

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

ObjectId.Parse(cool_id.ToString()) 中,我不断地收到 guid 是“无效的 24 位十六进制字符串”的错误提示 - 我做错了什么? - Vincent Buscarello
@VincentBuscarello,正如它所说,你的cool_id没有有效的字符串表示。也许可以使用ObjectId.TryParse(cool_id.ToString(), out ObjectId parsedResult)代替? - Sergei Kovalenko
@minhas-kamal,你能帮我解决上面的问题吗?我的情况下解决方案不起作用。https://stackoverflow.com/questions/74835380/how-to-do-a-partial-search-of-mongdb-object-id-in-c-sharp - Mohamed Sahir

4

如果您现在在2018年,并且想复制/粘贴仍然有效或使用纯字符串语法的代码;

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

3
所选答案是正确的。对于任何因Query.EQ感到困惑的人,这是另一种编写基本更新的方法(更新整个mongodb文档):
string mongoDocumentID = "123455666767778";
var query = new QueryDocument("_id", ObjectId.Parse(mongoDocumentID)); 
var update = new UpdateDocument { { "$set", documentToSave } };
mongoCollection.Update(query, update, UpdateFlags.Multi);

当您想要通过对象ID进行搜索时,需要使用ObjectId对象;否则,它将比较字符串和objectid类型,并且不会匹配。Mongo在这方面非常严格,无论字段名称是否正确。


0

你也可以这样做,它的

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

        return internalId;
    }

然后在你的方法中,你可以这样做

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

注意:GetInternalId方法中的id参数是该方法的一个参数。如果您需要,可以按照以下方式使用:
public async Task<YourTable> Find(string id)
    {
        ObjectId internalId = GetMongoId.GetInternalId(id);
        return await YourContext.YourTable.Find(c => c.InternalId == internalId).FirstOrDefaultAsync();
    }

希望它也能有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接