2012-07-06 172 views
1

这似乎是一个常见的用例...但不知何故,我无法得到它的工作。如何使用MongoDB作为唯一/枚举存储

我正在尝试使用MongoDB作为具有唯一项目的枚举存储。我创建了一个带有byte [] Id(唯一ID)和一个时间戳(一个long,用于枚举)的集合。该商店相当大(千兆字节),并分布在不同的服务器中。目前我能够从零开始重建商店,因为我仍处于测试阶段。

我想要做的是两两件事:

  1. 创建我插入每个项目的唯一ID。这基本上意味着如果我插入两次相同的ID,MongoDB将检测到这个并给出错误。这种方法似乎很好。
  2. 通过其他进程连续枚举新商品的商店。我采用的方法是为InsertID添加第二个索引,并在服务器ID和计数器上使用高精度时间戳(仅用于使其唯一并且升序)。

在最好的情况下,这将意味着枚举器会跟踪每个服务器的索引游标。从我从mongodb查询处理中学到的东西,我预料到了这种行为。但是,当我尝试执行代码(下面)时,似乎需要永远得到任何东西。

 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); 
     } 

我已阅读关于游标,但我不确定是否满足新条目插入商店时的要求。

正如我所说的,我没有绑定到任何表结构或类似的东西......唯一重要的是我可以随着时间的推移获得新的项目,而不会获得重复的项目。

-Stefan。

+0

我不确定如果我有你的问题!但是,为什么不让mongodb生成uniqueId。它已经做到了! – 2012-07-06 12:04:40

+0

你需要的是确保一个字符串不被枚举两次,或者用另一种方式说两个ID不应该有相同的值! – 2012-07-06 12:05:22

+0

听起来好像你正在使用分片(*多个计算机*)。这里你的碎片钥匙是什么?你有多少台服务器?通过跨多个服务器的二级索引查询可能是您的问题,但我需要更多关于您的配置的详细信息。 – 2012-07-06 22:51:46

回答

0

不知怎的,我想通了...或多或少...

我手动创建的查询,并结束了这样的事情:

db.documents.find({“InsertId “:{”$ gt“:NumberLong(”2020374866209304106“)}})。limit(10).sort({”InsertId“:1});

我放在问题中的LINQ查询不会生成此查询。后我发现,它应该是这样的LINQ查询代码一些挖掘:。

的foreach(在collection.AsQueryable()VAR项目凡((A)=>(a.InsertId> lastid))排序依据((a)=>(a.InsertId))。取(100))

AsQueryable()似乎是执行重写LINQ到MongoDB查询的关键。

这给出了结果,但它们似乎仍然很慢(10次结果为4秒,100次为30次)。但是,当我添加'explain()'时,我在查询执行中注意到'0毫秒'。

我停止了做批量插入和tada的过程,它的工作原理和快速。换句话说:我遇到的问题是由于MongoDB的锁定行为,以及由于我解释linq实现的方式。由于前者是初始批量填充数据存储的结果,这意味着问题得以解决。

在解决方案的'消极'部分:我会更喜欢一个解决方案,涉及可序列化游标或类似的东西......这个'采取'的解决方案必须一遍又一遍地重复b-tree。如果有人有这个答案,请让我知道。

-Stefan。

+0

1)因为总是从一个id开始排序(这可能是编入索引的),所以我没有看到自己在“遍历”b-tree的位置,而不是从id和index中取出100个项目。不知道如何得到其中的100个...... – 2012-07-09 12:12:45

+0

2)你的问题提到了多个读者。使用你这样做的方式,是什么阻止了两个不同的读者处理相同的记录? – 2012-07-09 12:13:39

+0

@CraigWilson它没有;我只是枚举每个“进程”的相同集合(例如索引等)。这是说实话,我想要做的并发,但实际上我刚刚解决了5分钟前的难题的部分:-) MongoDB有辉煌的事情,你可以连接到个别副本集并执行查询。如果您拥有的进程数与副本集数量一样多,则可以简单地枚举每个进程实例的一个副本集。其实这是我正在寻找的完整解决方案。顺便说一下:这个能力是MongoDB imho的一个辉煌的USP。 – atlaste 2012-07-09 15:43:20