sequelize + sequelize-hierarchy:如何在每个级别强制使用唯一的组织名称?

sequelize + sequelize-hierarchy: How enforce a unique organization name per level?

我有一个组织树,我想确保只有一个组织(使用它的 nameparent_id)在树的同一级别,即使在根级别.

例如:

有效树:

/org1 /org2

/org1/org2
     /org3

无效树:

/org1
/org1


/org1/org2
     /org2

型号:

var Organization = global.erp.orm.sequelize.define('Organization',
lodash.extend({}, global.erp.orm.mixins.attributes, {
  name      : {
    type     : global.erp.orm.Sequelize.STRING,
    comment  : 'The organization short name (its common referred name).',
    allowNull: false
  }
}), {
  comment  : 'An organization.',
  hierarchy: true
});

我尝试了以下但没有任何结果:

{
  comment  : 'An organization.',
  hierarchy: true,
  indexes     : [
    {
      unique: true,
      fields: ['parent_id', 'name']
    }
  ],
}

更新:

我将问题缩小到 parent_id 为 NULL 的情况,因此当其中一个值为 NULL 时,唯一复合索引似乎不起作用。

那么,有解决办法吗?

提前致谢。

此问题的原因在于 sqlite 和 mysql 解释 SQL-92 标准的方式。他们将每个 NULL 值视为唯一的。这就是为什么具有相同值和 NULL 的行是可能的。

您可以在此处阅读更多内容:https://www.sqlite.org/lang_createindex.html

如果您想尽可能保留 NULL 值,则无法使用模型中的默认 sequelize 索引声明来解决此问题。

但是您可以将这些字段声明为 NOT NULL 并提出您自己的默认 "nullish" 值,例如 0 或 -1。

仅使用复合索引的解决方案

尽管我已经将答案标记为已接受(并且我会保持这种状态,因为它为我指明了正确的方向,感谢@ezrepotein),我添加这个答案是为了完整性,因为这是我解决的方法问题。也许不是最好的解决方案,但它只使用唯一的复合索引就可以工作,这正是我想要的。

使用hierarchy_level作为签入变量:

{
  comment  : 'An organization.',
  hierarchy: true,
  indexes  : [
    {
      unique: true,
      fields: ['name', 'hierarchy_level'],
      where : {
        hierarchy_level: 1
      }
    },
    {
      unique: true,
      fields: ['name', 'parent_id'],
      where : {
        hierarchy_level: {
          $gt: 1
        }
      }
    }
  ]
}