MongoDB : 使用字符串而不是 BsonObjectId

MongoDB : Use string instead of BsonObjectId

我的游戏有 REST 服务,因此决定尝试 MongoDB - 除了“_id”字段要求外似乎很简单。

这里的问题是我的客户端应用程序正在使用 REST 服务并且不知道 "mongodb"、它的驱动程序或依赖项——也不应该。为了将客户端与服务器端(REST 服务提供者)分离,我需要解决 MongoDB 似乎需要 BsonObjectId 类型的“_id”字段这一事实。

目前我正在使用一个轻量级的 DAO 层,所以没有:

using System;

public class Item {
     private BsonObjectId _id;
     private string name;
}

我正在使用 DAO 将其翻译成某种东西 "mongodb agnostic":

using System;

public class ItemDAO {
     private string _id;
     private string name;
}

理想情况下,完全摆脱 BsonObjectId 会很好 - 是否有一些 annotation/custom 序列化处理程序可以使用,或者我可以使用字符串而不是 BsonObjectId 的某种方式?

如果做不到这一点,是否有任何方法可以让 MongoDB 包裹对象,以便用 _id 装饰它们,我可以将其作为字符串注入回行中?

理想的结果是完全没有 DAO class 只是 "Item" 并且让 Item 使用字符串作为 _id(或者不需要 mongodb 依赖项来流血的东西进入客户端实现)。

您的文档必须有一个 _id 字段,但不一定是 ObjectID。唯一的要求是它在集合中是唯一的。

如果您在保存新文档时没有提供 _id 字段,

MongoDB 将为您生成一个 ObjectId,但这只是一个辅助函数。

如何查询对象?如果您不想/不需要客户端中的 _id 字段,您可以使用 projection 从结果中排除 _id 字段。

另外请注意,生成您自己的基于字符串的 _id 会对数据库大小产生严重影响。 ObjectId 似乎是一个非常有效的结构。我已经尝试过对 _id 使用字符串,以避免在我永远不会使用的字段上建立索引 - 但在我的情况下,数据库大小的成本使其不可行。当然,取决于您的数据库大小和其余内容。

将 BSON ObjectIds 表示为字符串是司空见惯的事情;默认情况下,Mongo 驱动程序将生成 96 位 ID,然后您可以将其明显表示为 24 个十六进制字节。大多数客户端库都有从字符串中创建 ObjectIds 并将其转换为字符串的工具。

你会让你的外部接口把 _id 当作一个字符串,然后当你的 Mongo-aware DB 层收到一个 _id 作为一个字符串时,它只会在内部将它转换为 ObjectId.from_string(_id) 或诸如此类的东西。写入结果时,只需将 OID 转换为字符串即可。

使用 ObjectIds 作为主键的数据类型对 various reasons 很有意义。生成具有低碰撞概率的良好、非顺序、单调的 ID 并非易事,重新发明轮子或基本上重写功能是不值得的。

数据映射应该在控制器中完成,并且它们应该使用DTO与外部交互。换句话说,当您的数据库使用您的数据库模型时,您的 REST 端点 (Controllers/Modules) 应该是已知的 DTO。

DTO 看起来与您的模型非常相似,但它们的字段可能少一些(如果有您不想通过 API 公开的内部数据,则整洁)并且它们在模型中使用字符串使用 ObjectId。

为避免愚蠢的复制代码,请使用类似 AutoMapper.

的内容

如果您不想 "polute" 您的模型类,您可以在数据访问代码中注册适当的 ID 生成器。

BsonSerializer.RegisterIdGenerator(typeof(string), new StringObjectIdGenerator());

这样你的模型中就会有 String 字段,但在它下面是 ObjectId,这很好,即你可以看到添加记录的时间(大约)

但是,如果您决定在 REST 服务中接受来自客户端的 ID(通过 PUT),那么 ObjectId 显然不是正确的选择。

看看这个article,因为它描述了如何设置序列化选项等