【问题标题】:Are there ORM (OKM) for key-value stores?是否有用于键值存储的 ORM (OKM)?
【发布时间】:2011-05-05 04:32:51
【问题描述】:

Object-Relational-Mapper 旨在帮助应用程序(根据对象进行思考)以对应用程序更友好的方式处理存储的数据,就像所有其他类/对象一样。

但是,我从未见过用于 NoSQL“键/值”存储系统的 OKM(对象键/值映射器)。这看起来很奇怪,因为与常规的单个 SQL 表行对象相比,必须将更多的价值关系硬编码到应用程序中,因此需求应该大得多。

four requests:
user:id
user:id:name
user:id:email
user:id:created

vs one request:
user = [id => ..., name => ..., email => ...]

此外,您必须跟踪“列表”(发布 has_many cmets),因为您没有 has_many 通过表或外键。

INSERT INTO user_groups (user_id, group_id) VALUES (23, 54)

vs

usergroups:user_id = {54,108,32,..}
groupsuser:group_id = {23,12,645,..}

还有更多示例说明应用程序需要复制一些普通关系数据库使用的基本功能的附加逻辑。所有这些原因都让 OKM 的想法听起来很简单。

有吗?有什么理由没有吗?

【问题讨论】:

  • 键值对的 ORM?嗯..它会做什么,究竟是什么?问题或多或少是“值”或文档的序列化/反序列化。
  • @qstarin 我还不太确定,尽管它可以处理您的应用程序需要跟踪的关系(如列表)。当您离开 SQL 世界时,您的应用程序必须处理更多事情。

标签: database orm nosql


【解决方案1】:

Ruby 的 DataMapper 项目是一个 ORM,它很乐意通过使用适配器与键值存储进行对话。

RedisMongoDB 具有已存在的适配器。 CouchDB 有一个适配器——它没有被维护,但在某个时候它工作得很好。我认为还没有人对 Cassandra 做过任何事情,但没有理由不能做。 Google App Engine 的 Dubious framework 采用与 Data Mapper 非常相似的方法来使 Data Store 可用于应用程序。

所以很可能用键值存储来做 ORM。 ORM 只是真的需要避免假设 SQL 是它的主要词汇。

【讨论】:

  • 我要提到 CouchModel :P
  • 现在我只需要决定是否应该切换到 ruby​​ - 还是移植这些库之一。 dm-redis-adapter 看起来是在正确的轨道上。
【解决方案2】:

UNIVERSE db 是 Pick 的后代,可让您存储给定键的键值对列表。然而,这是一种非常古老的技术,很久以前世界就远离了这些数据库。

您可以在具有三列表的 SQL 数据库中实现这一点

  CREATE TABLE ATTRS ( KEYVAL VARCHAR(32),
                       ATTRNAME VARCHAR(32),
                       ATTRVAR  VARCHAR(1024)
                     )

如果您提出这个建议,尽管大多数 DBA 会用非常厚的 Codd 和 Date 精装版来打动您,但它实际上是打包应用程序中非常常见的模式,允许您将站点特定属性添加到系统中。

在 LISP 上转述 Richrd Stallmans cmets。 “任何功能合理的数据存储系统最终都会实现自己的 RDBMS 版本。”

【讨论】:

    【解决方案3】:

    SQL 的设计目标之一是可以在任何关系数据库中存储/查询任何数据 - 平台之间存在一些差异,但通常处理特定数据结构的正确方法是众所周知的并且很容易自动化,但需要相当冗长的代码。 NoSQL 并非如此 - 通常您将直接存储应用程序中使用的数据,而不是尝试将其映射到关系结构,并且没有连接或其他对象/关系差异,映射代码是微不足道的。

    除了生成样板数据访问代码之外,ORM 的主要目的之一是抽象平台之间的差异。根据我的经验,切换平台的能力一直是纯理论的,这种最低公分母方法根本不适用于 NoSQL,因为该平台通常是专门为其他平台上不存在的功能而选择的。您的示例仅适用于最简单的键值存储 - 根据您的平台,您很可能有一些有用的附加命令,因此您的第一个示例可能是

    MGET user:id:name user:id:email ...(multiget - 在一次调用中获取任意数量的键)

    GET user:id:*(关键通配符)

    HGETALL user:id (redis hash - 获取用户的所有子键)

    您还可以将您的用户对象以序列化形式存储 - 与关系数据库不同,这不会破坏您的所有查询。

    如果您的平台没有内置支持,那么使用列表并不是很好 - 原生列表/集合支持是我喜欢使用 redis 的原因之一 - 但除了可能需要锁之外,它并不比获取列表更糟糕没有sql。

    还值得注意的是,您可能不需要在 sql 中定义的所有关系 - 例如,如果您有一个包含一百万用户的组,那么获取组中所有用户的列表的能力是完全没用的,所以您根本不会创建 groupsuser 列表,而不是单独的 usergroups 列表将 user:id:groups 作为多值属性。如果您只需要检查成员资格,您可以将密钥设置为 usergroups:userid:groupid 并获得恒定时间查找。

    我发现从索引而不是关系的角度进行思考会有所帮助 - 在设置数据访问代码时,决定需要查询哪些字段并在写入这些字段时添加适当的索引记录。

    【讨论】:

    • 非常正确,NoSQL 数据库的不同功能集以及不同类型(文档与 KVP)当然意味着为每个数据库定制一个 ORM 包装器,以利用所有优势和设计选择。然而,我一直认为数据是有意义的关系,因为这就是在网页上请求它的方式。有人来查看帖子 - 并且还希望查看帖子标签和 cmets 或有人转到用户个人资料 - 并且还希望查看用户最近的活动。所以我知道必须有某种方法来编写可以关联数据的 OKM 包装器(或文档数据库的 ODM)。
    • 实际上,用户通常不会考虑任何类似于数据库中的内容,因此开发人员认为重要的是什么。 orm 的很大一部分价值在于能够访问 Post.Tags 而不是编写新查询。对于支持文档或多值列的数据库,标签已经是文档的一部分,因此不需要它。使用键值数据库在键中保存列表,您只需检索 post:id:tags 作为初始查询的一部分,因此不需要。
    • 对于像 cmets 这样关联的单独对象,没有架构或自动索引,因此无法从架构生成 orm 代码,并且您无法通过 comment.postid 查询,除非您手动设置,在这种情况下您最好还是直接使用本机 api - 例如: var a = GET commentindex:postId;管理一个
    • @Tom Clarkson 您在 post 对象中存储 Post 标签的第一个示例没有意义。标签的目的是找到相关的对象/帖子。但是,如果每个帖子的标签都嵌入到帖子对象中 - 那么您可以找到所有带有 star-wars 标记的帖子的唯一方法是获取每个帖子对象并查看它是否具有该标签。显然,这适用于超过 100 个帖子。至于您的第二条评论 - 您正在描述尝试将 SQL ORM 映射到 NoSQL 数据的失败,正如您所指出的那样,这将不起作用。我想了解如何将智能 OKM 对象映射到 NoSQL。
    • 对于存储来说非常有意义 - 当您显示帖子时,您希望在该帖子上显示标签。要查找其他帖子,您必须记住,对于大多数 NoSQL 系统,查询/搜索与存储完全分开 - 如果加载所有文档还不够好,您需要设置标签索引。 ORM 问题也适用于你所说的 OKM——你的意思要么是一个不值得作为单独系统开发的琐碎包装类,要么是更像全功能 ORM 的东西,由于 NoSQL 系统的性质,几乎不可能为它开发几乎没有什么好处。
    【解决方案4】:

    ORM 不能很好地映射到键值存储的无模式特性。话虽如此,如果您使用 Riak 和 Ruby,您可以查看 Ripple。 Riak 有许多其他驱动程序可能适合您的语言。

    如果您正在研究 MongoDB(更多的是文档存储而不是 k/v 存储),有许多 drivers 可用。

    【讨论】:

    • 正确的 ORM 不能很好地映射到键值存储 - 这就是我提出新类“OKM”的原因。毕竟,我们已经使用代码中的对象映射了从 XML 到图像到套接字到数据库结果的所有内容——为什么不映射键值存储呢?谢谢,我会看看Ripple。我不使用 ruby​​,但我可以从中获得一些想法。
    猜你喜欢
    • 2011-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 2021-04-03
    • 2011-01-15
    • 2018-12-16
    相关资源
    最近更新 更多