在MongoDB中获取已插入文档的_id?

43

假设我有一个产品列表。当我添加一个新产品时,我会使用类似以下的方法保存它:

var doc=products.Insert<ProductPDO>(p);
问题在于完成后我想将用户重定向到该产品的页面。因此,我需要重定向到 /products/<ObjectID>。但是,我没有找到一种不手动查询数据库并查找具有所有相同字段的文档的方法来立即获取 ObjectID。

是否有更简单的方法?(同时,在这种情况下,doc 返回 null,原因未知)

8个回答

75

Insert方法会自动设置已声明为模型BSON ID的属性。

如果如下声明...

[BsonId]
public ObjectId Id { get; set; }

如果将对象插入到集合中,则Id字段将包含对象的默认(新的、唯一的)BSON ID:

coll.Insert(obj);
// obj.Id is now the BSON ID of the object

1
对于那些较新的.NET开发者来说,这仍然不是很清楚。在哪个C#对象中可以提取新的ID?你能发布示例代码吗? - Vincent Buscarello
您可以从插入的类对象中提取ObjectId(Id)。 - Alde
1
这只适用于insertOne吗?它似乎不能用于insertMany... - mr_T
@mr_T 我在使用C#的InsertManyAsync时,发现调用后C#对象中的ID没有被填充。我一开始传递了一个LINQ Select (IEnumerable<>)的结果,但是后来改为传递了一个List<>,现在ID已经被填充了。请参考https://stackoverflow.com/questions/42605122/c-sharp-mongodb-insertmany-missing-id-after-insert。 - draketb

20
当您将一个对象插入到MongoDB中时,Mongo会使用内部ID来更新该对象。
因此,如果...
data = {
  title: "Howdy"
}

那么当我们将数据对象插入数据库时

db.collection('collectionName', function(err, collection) {
  collection.insert(data);
  console.log(data._id); // <- The mongodb id is now set on the item
});

6
如上评论所述,在您的模型中添加字段ID。
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string id { get; set; }

使用:

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

当您插入对象时,Mongo会将文档的ID返回到模型的ID字段中。


2
如果您知道ID的类型,可以尝试以下操作:

public static TId GetId<TId>(this BsonDocument document) where TId : struct
{
    if (document == default(BsonDocument))
    {
        throw new ArgumentNullException("document");
    }

    var id = document["_id"];

    object idAsObject;

    if (id.IsGuid)
    {
        idAsObject = (object)id.AsGuid;
    }
    else if (id.IsObjectId)
    {
        idAsObject = (object)id.AsObjectId;
    }
    else
    {
        throw new NotImplementedException(string.Format("Unknown _id type \"{0}\"", id.BsonType));
    }

    var idCasted = (TId)idAsObject;

    return idCasted;
}

使用方法如下:

Guid idOfDoc = myBsonDocument.GetId<Guid>();

尽管如此,您应该更喜欢选择答案中的专用属性...


2

在持久化之前,我将自定义类型 T 转换为 BsonDocument


var bsonDocument = item.ToBsonDocument();
_mongoCollection.InsertOne(bsonDocument);

T has a property Id:

[BsonId]
public ObjectId Id { get; set; }

当我调用ToBsonDocument()方法时,Id字段会被填充为ObjectId,然后推送到Mongo DB。这个方法会在代码中自己创建ID,而不是委托给Mongo DB来创建。但对我的情况来说已经足够了。"最初的回答"

1
class BsonID
{
    [BsonId]
    public ObjectId Id { get; set; }
}
var document = new BsonDocument {
   {"_id", new BsonID().Id },
   { "code", dr.Cells["code"].Value.ToString() },
   { "name", dr.Cells["name"].Value.ToString() },
  };
var customers = _database.GetCollection<BsonDocument>("Customers");
customers.InsertOne(document);
var id = document.ElementAt(0).Value.ToString();

0

将Class.Type作为BsonDocument而不是真正的Class.Type可能是此问题的常见原因:

e.g.:

var stream = mDB.GetCollection<vStreamMessage>(dictINI[sMONGODB_COLLECTION_NAME]);
            stream.InsertOne(msg);

不是

var stream = mDB.GetCollection<**BsonDocument**>(dictINI[sMONGODB_COLLECTION_NAME]);
            stream.InsertOne(**msg.ToBsonDocument**);

0

2021年:如果您正在使用C#9中的MongoDb和records,您可以使用以下技巧来获取插入的ID:

private async Task<T> AddEntity<T>(T entity, string collectionName) where T: EntityBase
{
    var col = _db.GetCollection<BsonDocument>(collectionName);
    var document = entity.ToBsonDocument();
    document["_id"] = ObjectId.Empty;
    await col.InsertOneAsync(document);
    var insertedEntity = entity with
    {
        id = document["_id"].ToString()!
    };
    return insertedEntity;
}

EntityBase 是您所有文档的基本实体,具有 id 字段。或者,您可以选择不使用泛型。


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