我应该使用哪种数据库模型在运行时动态修改实体/属性?

Jan*_*cke 20 python database sqlalchemy dynamic redis

我正在考虑为各种类型的数据创建一个开源数据管理Web应用程序.

特权用户必须能够

  • 添加新的实体类型(例如'用户'或'家庭')
  • 向实体类型添加新属性(例如'gender'到'user')
  • 删除/修改实体和属性

这些将是特权用户的常见任务.他将通过应用程序的Web界面执行此操作.最后,所有数据都必须可由应用程序的所有类型的用户进行搜索和排序.两个问题困扰我:

a)如何将数据存储在数据库中?我应该在运行时动态添加/删除数据库表和/或列吗?

我不是数据库专家.我坚持想象一下,在关系数据库方面,应用程序必须能够在运行时动态添加/删除表(实体)和/或列(属性).我不喜欢这个想法.同样,我在想是否应该在NoSQL数据库中处理这样的动态数据.

无论如何,我相信这种问题有一个智能的规范解决方案,到目前为止我还没有找到并想到这个解决方案.这种动态数据管理的最佳方法是什么?

b)如何使用ORM或NoSQL在Python中实现这一点?

如果您建议使用关系数据库模型,那么我想使用SQLAlchemy.但是,我没有看到如何在运行时使用ORM动态创建表/列.这是我希望在运行时创建表和列的方法更好的原因之一.使用SQLAlchemy可以高效地实现推荐的数据库模型吗?

如果你推荐使用NoSQL数据库,哪一个?我喜欢使用Redis - 您能想象基于Redis的高效实现吗?

谢谢你的建议!

编辑以回应一些评论:

这个想法是某个实体("表")的所有实例("行")共享同一组属性/属性("列").但是,如果某些实例的某些属性/属性具有空值,则它将完全有效.

基本上,用户将通过网站上的简单表单搜索数据.它们查询例如具有属性P的实体E的所有实例,其具有高于T的值V.结果可以按任何属性的值排序.

数据集不会变得太大.因此,我认为即使是最愚蠢的方法仍然会导致一个工作系统.但是,我是一个狂热爱好者,我想应用现代和适当的技术,以及我想知道理论上的瓶颈.我想使用这个项目来收集设计"Pythonic",最先进,可扩展,可靠的Web应用程序的经验.

我看到第一条评论倾向于推荐NoSQL方法.虽然我真的很喜欢Redis,但是看起来不利用Mongo/Couch的Document/Collection模型会很愚蠢.我一直在寻找用于Python的mongodb和mongoengine.通过这样做,我是否采取了正确的方向?

编辑2以回应一些答案/评论:

从最你的答案,我的结论是在关系图表和列的动态创建/删除是不是要走的路.这已经是有价值的信息.另外,有一种观点认为,对实体和属性进行动态修改的整个想法可能是糟糕的设计.

正如这种动态性质应该是应用程序的主要目的/特征,我不放弃这一点.从理论的角度来看,我接受在动态数据模型上执行操作必须比在静态数据模型上执行操作慢.这完全没问题.

以抽象的方式表达,应用程序需要管理

  1. 数据布局,即,有效的实体类型的"动态列表"和属性的每个有效实体类型"动态列表"
  2. 数据本身

我正在寻找一种智能有效的方法来实现这一点.从你的答案来看,看起来NoSQL是这里的方式,这是另一个重要的结论.

ran*_*lan 19

SQL或NoSQL选择不是你的问题.您需要阅读更多有关数据库设计的信息.正如您所说,您不是数据库专家(并且您不需要),但您绝对必须更多地学习RDBMS范例.

业余爱好者选择NoSQL解决方案是一个常见的错误.有时NoSQL是一个很好的解决方案,大多数时候都不是.

以你提到的MongoDB为例(这是我尝试过的优秀的NoSQL解决方案之一).无架构,对吧?呃...不完全是.你看到什么东西是无架构意味着没有约束,验证等.但你的应用程序的模型/实体不能忍受!当然,您在软件层上实施一些约束和验证逻辑.所以我给你mongokit!我将从项目的描述中引用这一点

MongoKit在伟大的pymongo驱动程序之上带来了结构化架构和验证层

嗯...非结构化变得有条理.

至少我们没有SQL吗?是的,我们没有.我们有一种不同的查询语言,当然不如SQL.至少你不需要使用map/reduce来进行基本查询(参见CouchDB).

不要误解我的意思,NoSQL(特别是MongoDB)有其目的,但大多数时候这些技术都是出于错误的原因.

此外,如果您关心严重的持久性和数据完整性,请忘记NoSQL解决方案.所有这些技术都具有实验性,无法保存您的严肃数据.通过研究一下(谷歌/亚马逊除外)使用NoSQL解决方案,究竟是什么,你会发现几乎没有人用它来保存他们的重要数据.他们主要使用它们来记录日志,消息和实时数据.基本上任何东西都可以从SQL数据库存储中减轻负担.

在我看来,Redis可能是唯一能够在NoSQL爆炸中幸免于难的项目.也许是因为它不会将自己宣传为NoSQL,而是作为一个键值存储,这正是它的本质和一个非常好的!他们似乎对持久性也很认真.这是瑞士军刀,但不是一个完全取代你的RDBMS的好方法.

对不起,我说得太多了:)

所以这是我的建议:

1)稍微研究一下RDBMS模型.

2)如果你的大多数项目都要使用RDBMS,Django是一个很好的框架.

3)Postgresql岩石!另请注意,9.2版将带来本机JSON支持.您可以在那里转储所有"动态"属性,并且可以使用辅助存储/引擎对所述属性执行查询(映射/缩减).你的蛋糕也吃了!

4)对于严肃的搜索功能,请考虑像solr这样的专用引擎.

编辑:2013年4月6日

5)django-ext-hstore允许您访问postgresql hstore类型.它类似于python字典,您可以对其执行查询,但不能将嵌套字典作为值.key的值也只能是类型string.

玩得开心


针对OP的评论进行更新

0)考虑应用程序"包含数据"并且已经使用了一段时间

我不确定你是否意味着它包含遗留dbms中的数据,或者你只是想说"想象数据库不是空的并考虑以下几点......".在前一种情况下,它似乎是一个迁移问题(完全不同的问题),在后一种情况下,还可以.

1)管理员删除实体"家庭"和所有相关数据

为什么有人要完全消除一个实体(表)?你的申请要么与家庭,房屋等有关,要么与之无关.当然,删除家庭的实例(行)是可以理解的.

2)管理员创建实体"房子"

与#1相同.如果您在应用程序中引入了一个全新的实体,那么很可能它将封装语义和业务逻辑,必须为其编写新代码.这发生在所有的应用程序,因为他们通过时间,当然权证的创建一个新表的进化,也许ALTER荷兰国际集团现有的一个.但是,此过程不是应用程序功能的一部分.即它很少发生,是一个迁移/重构问题.

3)管理员添加属性"楼层","年龄",..

为什么?我们事先不知道House有地板吗?那个User性别?动态添加和删除这种类型的属性不是一个功能,而是一个设计缺陷.分析/设计阶段是识别您的实体及其各自属性的一部分.

4)特权用户添加一些房屋.

是的,他正在向现有实体(表)添加一个实例(行)House.

5)用户搜索至少五层比100美元便宜的所有房屋

一个完全有效的查询,可以使用SQL或NoSQL解决方案实现.在django中,它将是这样的:

House.objects.filter(floors__gte=5, price__lt=100)
Run Code Online (Sandbox Code Playgroud)

只要House具有属性floorsprice.但是如果你需要进行基于文本的查询,那么SQL和NoSQL都不会令人满意.因为您不想自己实施切面干预!您将使用一些已经讨论过的解决方案(Solr,ElasticSearch等).

一些更一般的说明:

你给了有关的例子Houses,Users和它们的属性,不保证任何动态模式.也许你简化了你的例子只是为了说明你的观点,但你谈到添加/删除Entities(tables)它们就好像它们是db中的行一样.实体在应用程序中应该是一个大问题.它们定义了应用程序的用途及其功能.因此,他们不能每分钟都改变.

你也说过:

The idea is that all instances ("rows") of a certain entity ("table") share the same set of properties/attributes ("columns"). However, it will be perfectly valid if certain instances have an empty value for certain properties/attributes.
Run Code Online (Sandbox Code Playgroud)

这似乎是属性具有的常见情况null=True.

作为最后一点,我建议你尝试两种方法(SQL和NoSQL),因为你的职业生涯似乎并不依赖于这个项目.这将是一种受益体验,因为您将直接了解每种方法的缺点和优点.甚至如何将这些方法"融合"在一起.

  • 好吧,你的一厢情愿.到处都需要结构!您要么在数据库层或业务逻辑层中拥有它.没有其他办法了. (2认同)

Chr*_*son 6

您要问的是许多系统中的常见要求 - 如何扩展核心数据模型以处理用户定义的数据.这是打包软件(通常以单向处理)和开源软件(以另一种方式处理)的流行要求.

早期了解RDBMS设计的建议通常不会受到影响.我将添加的内容是,不要陷入在您自己的特定于应用程序的数据模型中重新实现关系数据库的陷阱!我已经多次看到过这种情况,通常是在打包的软件中.不希望向最终用户公开核心数据模型(或更改它的权限),开发人员创建通用数据结构和应用程序接口,允许最终用户定义实体,字段等但不使用RDBMS工具.这通常是一个错误,因为很难像经验丰富的RDBMS为您做的那样彻底或无错误,并且可能需要花费很多时间.这很诱人,但恕我直言不是一个好主意.

假设数据模型更改是全局的(一旦管理员创建它们就会被所有用户共享),我将解决此问题的方法是创建一个位于admin用户和RDBMS之间的应用程序界面,并应用您需要的任何规则适用于数据模型更改,但随后将最终更改传递给RDBMS.例如,您可能有规则说实体名称需要遵循某种格式,允许新实体具有现有表的外键但必须始终使用DELETE CASCADE规则,字段只能是某些数据类型,所有字段必须有默认值等.您可以有一个非常简单的屏幕,要求用户提供实体名称,字段名称和默认值等,然后生成SQL代码(包括所有规则)以对数据库进行这些更改.

一些常见规则以及如何解决这些问题将是:

- 如果某个字段不为空并且具有默认值,并且在管理员添加该字段之前表中已存在记录,则在创建字段时更新现有记录以具有默认值(多个步骤 - 添加允许null的字段;更新所有现有记录;更改表以强制非null(默认值) - 否则您将无法使用字段级完整性规则)

- 新表必须具有不同的命名模式,以便您可以继续区分核心数据模型和用户扩展数据模型,即核心和用户定义具有不同的RDBMS所有者(dbo.与用户.)或前缀(无)对于核心,__为用户定义的)或某些.

- 可以向核心数据模型中的表添加字段(只要它们容忍空值或具有默认值),管理员可以删除管理员添加到核心数据模型表的字段,但管理员可以无法删除已定义为核心数据模型一部分的字段.

换句话说 - 使用RDBMS的强大功能来定义表并管理数据,但为了确保始终应用您需要的任何约定或规则,请通过构建app-to-DB管理功能来实现此目的.给管理员用户直接DB访问权限.

如果你真的只想通过数据库层来实现这一点,那么你可以通过创建一堆实现相同逻辑的存储过程和触发器来实现同样的目标(并且谁知道,也许你会为你的应用程序做到这一点).这可能更像是一个问题,即您的管理员用户在数据库层中工作与通过中间应用程序相比有多舒适.


所以直接回答你的问题:

(1)是的,在运行时添加表和列,但考虑一下即使添加了用户定义的数据也需要确保应用程序可以运行的规则,并选择一种方法来强制执行这些规则(通过应用程序或当您处理表和字段更改时,通过DB /存储过程或其他).

(2)您选择的SQL与NoSQL引擎不会对此问题产生很大影响.在每种情况下,您都拥有核心数据模型和扩展数据模型.如果您可以设计应用程序以响应动态数据模型(例如,在将字段添加到数据库表或其他任何内容时向屏幕添加新字段),那么您的应用程序将很好地响应核心和用户定义数据模型中的更改.这是一个有趣的挑战,但对DB实现风格的选择影响不大.

祝好运!


And*_*rts 3

因此,如果您将实体概念化为“文档”,那么整个问题就可以很好地映射到 no-sql 解决方案上。正如所评论的,您需要有某种模型层,位于文档存储之上并执行验证等任务,并且可能强制(或鼓励)某种模式,因为没有隐式后端要求实体中的实体同一集合(与表并行)共享架构。

允许特权用户更改您的架构概念(而不是仅向单个文档添加字段 - 这很容易支持)将带来一些挑战 - 您必须处理迁移现有数据以自动匹配新架构。

阅读您的编辑,Mongo 支持您正在寻找的搜索/排序类型,并将为您提供所需的“空单元格”(缺少特定键的文档)支持。

如果我是你(而且我目前正在开发一个类似但更简单的产品),我会坚持使用 Mongo 并研究像 Flask 这样的轻量级 Web 框架来提供前端。您将自己提供模型,但您不会与框架的隐式建模选择作斗争。