设为首页 收藏本站
查看: 776|回复: 0

[经验分享] MongoDB学习笔记~ObjectId主键的设计

[复制链接]

尚未签到

发表于 2015-7-6 11:27:12 | 显示全部楼层 |阅读模式
  回到目录

说一些关于ObjectId的事
  MongoDB确实是最像关系型数据库的NoSQL,这在它主键设计上可以体现的出来,它并没有采用自动增长主键,因为在分布式服务器之间做数据同步很麻烦,而是采用了一种ObjectId的方式,它生成方便,占用空间比long多了4个字节,(12个字节)在数据表现层面也说的过去,它是一种以时间,机器,进程和自增几个因素组合的方式来体现的,可以近似看成是按时间的先后进行排序的,对于ObjectId的生成我们可以通过MongoDB服务端去获得,或者在客户端也有对它的集成,使用方便,一般情况下,在客户端实体类中只要定义一个ObjectId类型的属性,这个属性就默认被赋上值了,应该说,还是比较方便的,由于它存储是一种字符串,所以,一般客户端,像NoRM都为我们实现了对string类型的隐藏转换,应该说,还是比较友好的!

ObjectId的组成


为何选择十六进制表示法

  为什么在ObjectId里,将byte[]数组转为字符串时,使用十六进制而没有使用默认的十进制呢,居 我的研究,它应该是考虑字符串的长度一致性吧,因为byte取值为(0~255),如果使用默认的十进制那么它的值长度非常不规范,有1位,2位和3位, 而如果使用十六进制表示,它的长度都为2位,2位就可以表示0到255中的任何数字了,0对应0x00,255对应0xFF,呵呵,将它们转为字符串后,即可 以保证数据的完整性,又可以让它看上去长度是一致的,何乐不为呢,哈哈!
  漂亮的设计,原自于扎实的基础!


在C#版的NoRM这样设计ObjectId



        ///
/// Generates a byte array ObjectId.
///
///
///
public static byte[] Generate()
{
var oid = new byte[12];
var copyidx = 0;
//时间差
Array.Copy(BitConverter.GetBytes(GenerateTime()), 0, oid, copyidx, 4);
copyidx += 4;
//机器码
Array.Copy(machineHash, 0, oid, copyidx, 3);
copyidx += 3;
//进程码
Array.Copy(procID, 0, oid, copyidx, 2);
copyidx += 2;
//自增值
Array.Copy(BitConverter.GetBytes(GenerateInc()), 0, oid, copyidx, 3);
return oid;
}
  完整的ObjectId类型源代码
  它重写的ToString()方法,为的是实现byte[]到string串之间的类型转换,并且为string和ObjectId对象实现 implicit的隐式类型转换,方便开发人员在实际中最好的使用它们,需要注意的是在byte[]中存储的数据都是以十六进制的形式体现的



    ///
/// Represents a Mongo document's ObjectId
///
[System.ComponentModel.TypeConverter(typeof(ObjectIdTypeConverter))]
public class ObjectId
{        
private string _string;
///
/// Initializes a new instance of the  class.
///
public ObjectId()
{
}
///
/// Initializes a new instance of the  class.
///
///
/// The value.
///
public ObjectId(string value)
: this(DecodeHex(value))
{
}
///
/// Initializes a new instance of the  class.
///
///
/// The value.
///
internal ObjectId(byte[] value)
{
this.Value = value;
}
///
/// Provides an empty ObjectId (all zeros).
///
public static ObjectId Empty
{
get { return new ObjectId("000000000000000000000000"); }
}
///
/// Gets the value.
///
/// The value.
public byte[] Value { get; private set; }
///
/// Generates a new unique oid for use with MongoDB Objects.
///
///
///
public static ObjectId NewObjectId()
{
// TODO: generate random-ish bits.
return new ObjectId { Value = ObjectIdGenerator.Generate() };
}
///
/// Tries the parse.
///
///
/// The value.
///
///
/// The id.
///
///
/// The try parse.
///
public static bool TryParse(string value, out ObjectId id)
{
id = Empty;
if (value == null || value.Length != 24)
{
return false;
}
try
{
id = new ObjectId(value);
return true;
}
catch (FormatException)
{
return false;
}
}
///
/// Implements the operator ==.
///
/// A.
/// The b.
/// The result of the operator.
public static bool operator ==(ObjectId a, ObjectId b)
{
if (ReferenceEquals(a, b))
{
return true;
}
if (((object)a == null) || ((object)b == null))
{
return false;
}
return a.Equals(b);
}
///
/// Implements the operator !=.
///
/// A.
/// The b.
/// The result of the operator.
public static bool operator !=(ObjectId a, ObjectId b)
{
return !(a == b);
}
///
/// Returns a hash code for this instance.
///
///
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
///
public override int GetHashCode()
{
return this.Value != null ? this.ToString().GetHashCode() : 0;
}
///
/// Returns a  that represents this instance.
///
///
/// A  that represents this instance.
///
public override string ToString()
{
if (this._string == null && this.Value != null)
{
this._string = BitConverter.ToString(this.Value).Replace("-", string.Empty).ToLower();
}
return this._string;
}
///
/// Determines whether the specified  is equal to this instance.
///
///
/// The  to compare with this instance.
///
///
/// true if the specified  is equal to this instance; otherwise, false.
///
public override bool Equals(object o)
{
var other = o as ObjectId;
return this.Equals(other);
}
///
/// Equalses the specified other.
///
///
/// The other.
///
///
/// The equals.
///
public bool Equals(ObjectId other)
{
return other != null && this.ToString() == other.ToString();
}
///
/// Decodes a HexString to bytes.
///
///
/// The hex encoding string that should be converted to bytes.
///
///
///
protected static byte[] DecodeHex(string val)
{
var chars = val.ToCharArray();
var numberChars = chars.Length;
var bytes = new byte[numberChars / 2];
for (var i = 0; i < numberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(new string(chars, i, 2), 16);
}
return bytes;
}
/// TODO::Description.
public static implicit operator string(ObjectId oid)
{
return oid == null ? null : oid.ToString();
}
/// TODO::Description.
public static implicit operator ObjectId(String oidString)
{
ObjectId retval = ObjectId.Empty;
if(!String.IsNullOrEmpty(oidString))
{
retval = new ObjectId(oidString);
}
return retval;
}
}
  ObjectIdGenerator源代码
  它主要实现了ObjectId串生成的规则及方式



    ///
/// Shameless-ly ripped off, then slightly altered from samus' implementation on GitHub
/// http://github.com/samus/mongodb-csharp/blob/f3bbb3cd6757898a19313b1af50eff627ae93c16/MongoDBDriver/ObjectIdGenerator.cs
///
internal static class ObjectIdGenerator
{
///
/// The epoch.
///
private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
///
/// The inclock.
///
private static readonly object inclock = new object();
///
/// The inc.
///
private static int inc;
///
/// The machine hash.
///
private static byte[] machineHash;
///
/// The proc id.
///
private static byte[] procID;
///
/// Initializes static members of the  class.
///
static ObjectIdGenerator()
{
GenerateConstants();
}
///
/// Generates a byte array ObjectId.
///
///
///
public static byte[] Generate()
{
var oid = new byte[12];
var copyidx = 0;
//时间差
Array.Copy(BitConverter.GetBytes(GenerateTime()), 0, oid, copyidx, 4);
copyidx += 4;
//机器码
Array.Copy(machineHash, 0, oid, copyidx, 3);
copyidx += 3;
//进程码
Array.Copy(procID, 0, oid, copyidx, 2);
copyidx += 2;
//自增值
Array.Copy(BitConverter.GetBytes(GenerateInc()), 0, oid, copyidx, 3);
return oid;
}
///
/// Generates time.
///
///
/// The time.
///
private static int GenerateTime()
{
var now = DateTime.Now.ToUniversalTime();
var nowtime = new DateTime(epoch.Year, epoch.Month, epoch.Day, now.Hour, now.Minute, now.Second, now.Millisecond);
var diff = nowtime - epoch;
return Convert.ToInt32(Math.Floor(diff.TotalMilliseconds));
}
///
/// Generate an increment.
///
///
/// The increment.
///
private static int GenerateInc()
{
lock (inclock)
{
return inc++;
}
}
///
/// Generates constants.
///
private static void GenerateConstants()
{
machineHash = GenerateHostHash();
procID = BitConverter.GetBytes(GenerateProcId());
}
///
/// Generates a host hash.
///
///
///
private static byte[] GenerateHostHash()
{
using (var md5 = MD5.Create())
{
var host = Dns.GetHostName();
return md5.ComputeHash(Encoding.Default.GetBytes(host));
}
}
///
/// Generates a proc id.
///
///
/// Proc id.
///
private static int GenerateProcId()
{
var proc = Process.GetCurrentProcess();
return proc.Id;
}
}
  事实上,通过对NoRm这个MongoDB客户端的学习,让我们的眼界放宽了许多,可能在思考问题时不局限于眼前,对于同一个问题可以会有更多的解决方法了,呵呵!
  回到目录

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-83788-1-1.html 上篇帖子: MongoDB-索引 下篇帖子: windows下mongodb基础玩法系列二CURD附加一
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表