Couchdb中任意谓词查询的策略

时间:2011-01-24 09:17:42

标签: mongodb couchdb

我们有一个应用程序可以从使用像CouchDB这样的基于文档的数据存储中获益匪浅。但我们有一个查询用例,我正在努力用Map Reduce实现。

我们的文档实际上只包含两种类型的数据:

  1. 数字属性
  2. 布尔属性
  3. 布尔属性实质上将文档标记为属于一个或多个非独占集合。数字属性始终只需要求和。构建文档的一种方法是这样的:

    {
      "id": 3123123,
      "attr": {"x": 2, "y": 4, "z": 6},
      "sets": ["A", "B", "C"]
    }
    

    使用这种结构,可以很容易地计算出集合A,B和C的聚合x,y,z值,但是当你想要看到像A& C这样的交叉点的聚合时,它会变得更加复杂。

    在这个小案例中,我可以为ABC的所有排列(“A,B,C,AB,AC,BC,ABC”)发出密钥,但我担心这会如何扩展。我们的文档可能属于80集的某种组合,它由用户界面构成,可以构建任何可能的组合。

    我倾向于认为这不是CouchDB的工作,也许MongoDB或其他东西更适合这个问题。

    我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

可以有效地计算和缓存所有这些值的数据结构将非常复杂。我不确定任何数据库系统都可以在不迭代子集的情况下执行此操作。交叉口是一个众所周知的艰难操作,而且CouchDB没有任何可用的东西来正确处理交叉点。

正如您所正确识别的那样,发出所有排列(确切地说是子集)将成为记忆困难,因为它仍然会使您的项目乘以一个巨大的因素(2 n n组的键值对)。您可以通过将前缀折叠在一起来减少这种情况(当您使用组级别选项发出["A"]时,CouchDB键结构可让您检索["A","B"]["A","B","C"]的值)但仅限于一个因子2(2个 n-1 键组对n组)。

所以,如果你的项目平均有三个相关的集合,那么你会很好(4个键值对而不是3个),但是4个相关集合更重(8个而不是4个),并且有5个开始变得讨厌(16而不是5)。这也使得具有许多关联集的项容易受到性能问题的影响(10组项目将创建超过500个键值对)。

中间接地方法是发出长度最多为四组的密钥(它只是所需内存的两倍),并在需要更深的交叉点时运行一些应用程序端处理(抓取所有项目而不减少,运行减少在申请中)。幸运的是,相关项目的数量将会更小 - 如果不是这样,您可以始终使用最大设置大小来牺牲更多内存以获得更高性能。

相反的方法是在插入/更新每个文档时(通过获取与当前项的子集匹配的所有“总计”文档)使应用程序更新2 n 总计。这些总计将存储在不同的数据库中,并将通过密钥进行查询。如果您能够动态更新总计(或者您的架构允许您通过监听主数据库中的更新来更新它们),这种方法会更好,因为它可以快速查询查询。