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 个十六进制字节。大多数客户端库都有从字符串中创建 ObjectId
s 并将其转换为字符串的工具。
你会让你的外部接口把 _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,因为它描述了如何设置序列化选项等
我的游戏有 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 个十六进制字节。大多数客户端库都有从字符串中创建 ObjectId
s 并将其转换为字符串的工具。
你会让你的外部接口把 _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,因为它描述了如何设置序列化选项等