2011-05-04 147 views
0

我正在构建一个应用程序,它将在MongoDB集合上定期进行离线匹配。然而,我需要做的是获得以前没有匹配过的所有可能匹配的列表。NOT IN(SELECT * FROM X)等效于MongoDB

因此,举例来说,假设下列对象(简化,使这个更具可读性):

person { _id: 1, name: 'Matt', previouslyMatched: [2] }

person { _id: 2, name: 'John', previouslyMatched: [1] }

person { _id: 3, name: 'Tony', previouslyMatched: [] }

我想运行马特查询(ID :1)确定是否有其他人员记录不在previousMatched数组中。

现在在SQL中,我会像SELECT ID FROM person WHERE ID <> 1 AND ID NOT IN (SELECT match_id from person_match where person_id = 1) 这样假设当然,我有一个名为person_match的查找表,其中存储了所有以前匹配的列person_id和match_id。我意识到在这个查询中存在潜在的性能缺陷,但请耐心等待,因为这只是一个示例,其他优化将完成。

在MongoDB中,我只是不清楚如何去做这件事。我当然可以检索人员文档(id:1),然后检索所有其他人员文档,并检查ID是否位于previousMatched阵列客户端,但是我担心这会导致性能不必要的大数据从数据库服务器传输到客户端。

我知道这里有一个$nin函数,但是我已经读过这个函数的性能不是很好,并且我不知道它是多么明智的一个想法,它传递了一个潜在的非常长的数组ID到我的应用程序扩展到这个领域。

我的直觉告诉我,答案可能在于Server side code execution,但我不清楚这是如何实现的。

最后,我还担心实际上有多少物品可以存储在单个数组字段中。是否有实际限制?

谢谢, 马特

回答

0

您必须执行多个查询...还有什么比一个子选择MongoDB中或在应用端执行一些明确的过滤。

+0

哦,这可能会在I/O方面变得昂贵,特别是在使用托管的MongoDB时。是否没有编写一些JavaScript代码的方式来有效地使用服务器端代码执行这些查找?这至少可以减少数百/数千个请求的潜在需求。 – 2011-05-05 15:40:21

3

这听起来像你正试图在这里做一个加入。它不完全是一个连接,但SQL IN语法有效地允许您将一组数据的输出应用于另一组数据。

无论哪种情况,MongoDB都不支持连接,并且不支持WHERE IN (subtable)语法。您提到的$in语法等同于WHERE IN (a,b,c),并带有固定列表。

我在这里可以看到的唯一方法涉及多个查询(2个或更多)或某种形式的客户端处理。

我的直觉告诉我,答案可能在于服务器端代码执行,...

服务器端代码执行有大约锁定一定的局限性。如果你想做这个查询很多,我不相信服务器端代码将有效地解决这个问题。

最后,我还担心实际上有多少物品可以存储在单个数组字段中。是否有实际限制?

一个MongoDB文档只能包含16MB的数据。这是一个很难的物理限制。

64位整数需要8 bytes。所以这是几百万的整数。字符串明显少得多。

我个人的经验法则是数千或数万(取决于数据)。如果您需要存储“数十万”,那么您可能会遇到16MB的限制。

+0

Thanks @ gates,这非常有用。我将在此基础上研究解决方案,并在完成后回来发布我的发现。最后一个问题,我可以找到更多关于执行服务器端代码时可能发生的锁定的建议吗? – 2011-05-06 09:11:52

+0

现在没有很好的记录。这是基本的前提。每个'mongod'进程都有一个javascript引擎实例。如果你这样做了“服务器端”查询,你正在锁定那个单一的实例。通常情况下,MongoDB有一个写锁,但可以读多个内核。如果你正在运行这个“存储过程”,那么你正在利用这个核心。您还在与Map/Reduce或任何其他'eval()'调用竞争。 – 2011-05-06 22:30:39

相关问题