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

时间:2015-09-04 18:32:00

标签: javascript sql node.js orm sequelize.js

我是一个组织'树,并希望确保在树中的同一级别只有一个组织(使用其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时,似乎唯一的复合索引不起作用。

那么,有一个解决方案吗?

提前致谢。

2 个答案:

答案 0 :(得分:2)

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

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

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

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

答案 1 :(得分:0)

仅使用复合指数的解决方案

虽然我已经将答案标记为已接受(并且我会保持这种方式,因为它指向了正确的方向,感谢@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
        }
      }
    }
  ]
}