C# 如何使用MongoDB作为唯一/枚举存储
这似乎是一个常见的用例。。。但不知何故,我无法让它工作 我试图将MongoDB用作具有唯一项的枚举存储。我创建了一个具有byte[]Id(唯一Id)和时间戳(长,用于枚举)的集合。存储相当大(TB),分布在不同的服务器上。我现在能够从头开始重建商店,因为我仍处于测试阶段 我想做的是两件事:C# 如何使用MongoDB作为唯一/枚举存储,c#,mongodb,enumeration,bigdata,C#,Mongodb,Enumeration,Bigdata,这似乎是一个常见的用例。。。但不知何故,我无法让它工作 我试图将MongoDB用作具有唯一项的枚举存储。我创建了一个具有byte[]Id(唯一Id)和时间戳(长,用于枚举)的集合。存储相当大(TB),分布在不同的服务器上。我现在能够从头开始重建商店,因为我仍处于测试阶段 我想做的是两件事: 为我插入的每个项目创建一个唯一的id。这基本上意味着,如果我插入相同的ID两次,MongoDB将检测到这一点并给出一个错误。这种方法似乎很有效 通过其他流程不断枚举存储区中的新项目。我采取的方法是向Inser
long lastid = 0;
while (true)
{
DateTime first = DateTime.UtcNow;
foreach (var item in collection.FindAllAs<ContentItem>().OrderBy((a)=>(a.InsertId)).Take(100))
{
lastid = item.InsertId;
}
Console.WriteLine("Took {0:0.00} for 100", (DateTime.UtcNow - first).TotalSeconds);
}
long lastid=0;
while(true)
{
DateTime first=DateTime.UtcNow;
foreach(collection.FindAllAs()中的var项。OrderBy((a)=>(a.InsertId)).Take(100))
{
lastid=item.InsertId;
}
WriteLine(“用{0:0.00}表示100”,(DateTime.UtcNow-first).TotalSeconds);
}
我读过有关游标的文章,但不确定在商店中插入新项目时它们是否满足要求
正如我所说,我不受任何表结构或类似结构的约束。。。唯一重要的是,随着时间的推移,我可以得到新的项目,而不会得到重复的项目
-斯蒂芬。不知怎的,我弄明白了。。。或多或少 我手动创建了查询,结果如下: find({“InsertId”:{“$gt”:NumberLong(“2020374866209304106”)}).limit(10).sort({“InsertId”:1}) 我在问题中提出的LINQ查询不会生成此查询。在深入研究代码之后,我发现应该是这样的LINQ查询: foreach(collection.AsQueryable()中的var项,其中((a)=>(a.InsertId>lastid)).OrderBy((a)=>(a.InsertId)).Take(100)) AsQueryable()似乎是执行LINQ到MongoDB查询重写的关键 这给出了结果,但仍然显得很慢(10个结果4秒,100个结果30秒)。但是,当我添加“explain()”时,我注意到查询执行中有“0毫秒” 我停止了批量插入和tada的过程,它工作正常,而且速度很快。换句话说:我遇到的问题是由于MongoDB的锁定行为,以及我解释linq实现的方式。由于前者是初始批量填充数据存储的结果,这意味着问题已经解决 关于解决方案的“负面”部分:我更喜欢包含可序列化游标或类似内容的解决方案。。。这个“take”解决方案必须反复迭代b-树。如果有人对此有答案,请告诉我
-Stefan.我不确定是否有你的问题!但是,为什么不让mongodb生成uniqueId呢。它已经做到了!不过,您需要确保一个字符串不会被枚举两次,或者以另一种方式表示两个ID的值不应该相同!听起来像是在使用分片(多台计算机)。你的碎片钥匙是什么?你有多少台服务器?在多个服务器之间通过辅助索引进行查询可能是您的问题,但我需要有关您的配置的更多详细信息。@Ozair:我生成一个唯一的id,因为我使用它进行重复检测。(1) ID基本上是我插入的内容的MD5散列;如果我插入它两次,它将发生冲突并给出一个错误——这是正确的。@GatesVP Yes您是正确的:目前我们对14个MongoDB实例使用切分(将来可能会增加)。切分键是MD5散列。辅助键是插入的ID。换句话说,我确实希望一个枚举查询能够到达14台服务器。但是,对于一个有100个结果的查询来说,20秒太长了;我所期望的行为是,查询进入所有服务器,获取10个结果(你可以很容易地从统计数据中推断出来,因为每台服务器持有的文档数量或多或少相等),合并它们并将它们发送回客户端。1)因为它们总是从一个id开始排序(可能是索引的),然后,除了id和索引中的100项之外,我看不到在哪里“迭代”b树。我不知道怎么才能得到100个……2)你的问题提到了多个读者。用你现在的方式,是什么阻止了两个不同的阅读器处理同一条记录呢?@CraigWilson it没有;我只是为每个“进程”(例如索引等)枚举相同的集合。老实说,我想同时做一些事情,但实际上我在5分钟前刚刚解决了这个难题的一部分:-)MongoDB有一个绝妙的功能,您可以连接到单个副本集并执行查询。如果流程实例的数量与副本集的数量相同,则可以简单地为流程的每个实例枚举一个副本集。事实上,这就是我一直在寻找的完整解决方案。顺便说一句:这个能力对于MongoDB imho来说是一个非常好的USP。@CraigWilson顺便说一句,我并不真正关心100或500或任何批量大小。我更希望MongoDB只给我任何方便的批量大小——这可能是B树中的一个页面。光标就是页面id,'>=x-take-y'只是告诉MongoDB“给我一个光标”