繁体   English   中英

如何在关系数据库中存储智能列表规则

[英]How to store smart-list rules in a relational database

我正在建立的系统有智能组。 智能组是指基于以下规则自动更新的组:

  1. 包括与给定客户关联的所有人员。
  2. 包括与给定客户关联并具有这些职业的所有人员。
  3. 包括特定的人(即通过ID)

每个智能组可以组合任意数量的这些规则。 因此,例如,特定的智能列表可能具有以下特定规则:

  1. 包括与客户端1关联的所有人员
  2. 包括与客户5关联的所有人员
  3. 包括人6
  4. 包括与客户10关联的所有人员,以及具有职业2,6和9的人员

这些规则被组合在一起形成组。 我正在考虑如何在数据库中最好地存储它,因为除了支持这些规则之外,我希望将来能够添加其他规则而不会有太多痛苦。

我想到的解决方案是为每种规则类型设置一个单独的模型。 该模型将有一个方法,它返回一个查询集,可以与其他规则的查询集结合,最终得出一个人的列表。 我可以看到的一个缺点是每个规则都有自己的数据库表。 我应该关注这件事吗? 是否有更好的方法来存储这些信息?

为什么不使用Q对象

rule1 = Q(client = 1)
rule2 = Q(client = 5)
rule3 = Q(id = 6)
rule4 = Q(client = 10) & (Q(occupation = 2) | Q(occupation = 6) | Q(occupation = 9))

people = Person.objects.filter(rule1 | rule2 | rule3 | rule4)

然后将他们的pickle字符串存储到数据库中。

rule = rule1 | rule2 | rule3 | rule4
pickled_rule_string = pickle.dumps(rule)
Rule.objects.create(pickled_rule_string=pickled_rule_string)

以下是我们为处理此方案而实施的模型。

class ConsortiumRule(OrganizationModel):
    BY_EMPLOYEE = 1
    BY_CLIENT = 2
    BY_OCCUPATION = 3
    BY_CLASSIFICATION = 4
    TYPES = (
        (BY_EMPLOYEE, 'Include a specific employee'),
        (BY_CLIENT, 'Include all employees of a specific client'),
        (BY_OCCUPATION, 'Include all employees of a speciified  client ' + \
            'that have the specified occupation'),
        (BY_CLASSIFICATION, 'Include all employees of a specified client ' + \
            'that have the specified classifications'))

    consortium = models.ForeignKey(Consortium, related_name='rules')
    type = models.PositiveIntegerField(choices=TYPES, default=BY_CLIENT)
    negate_rule = models.BooleanField(default=False,
        help_text='Exclude people who match this rule')


class ConsortiumRuleParameter(OrganizationModel):
    """ example usage: two of these objects one with "occupation=5" one
    with "occupation=6" - both FK linked to a single Rule
    """

    rule = models.ForeignKey(ConsortiumRule, related_name='parameters')
    key = models.CharField(max_length=100, blank=False)
    value = models.CharField(max_length=100, blank=False)

起初我对这个解决方案有抵触,因为我不喜欢在CharField中存储对其他对象的引用的想法(CharField被选中,因为它是最通用的。后来,我们可能有一个规则匹配任何人的名字以'Jo'开头)。 但是,我认为这是在关系数据库中存储此类映射的最佳解决方案。 这是一个很好的方法的一个原因是清理悬挂引用相对容易。 例如,如果公司被删除,我们只需要:

ConsortiumRuleParameter.objects.filter(key='company', value=str(pk)).delete()

如果参数存储为序列化对象(例如,评论中建议的Q对象),则这将更加困难且耗时。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM