2017-05-16 10 views
1

我有一个相当复杂的关系与多态直通模型。在应用中,有一个标签系统,用户和另一个模型可以被标记。为了避免重复的字符串条目,我使用了一个包含标记ID,标记的模型名称和标记的实例ID的直通模型(TagLink)。避免重复多态hasAndBelongsToMany通过模型关系

所以我

User --+ 
     | 
     +---> TagLink -----------> Tag 
     |  - tagId    - id 
Item --+  - taggableId   - text 
       - taggableName 
       (User or Item) 

的链接关系是hasAndBelongsToMany。问题是,当我发布一个新标签到/items/:id/tags/users/:id/tags时,它被保存,但我可以创建尽可能多的相同的文本没有任何错误。

我想什么,在张贴到/items/:id/tags/users/:id/tags,它:

  • 创建一个新的标签条目,如果没有已经存在,然后添加一个新的TagLink条目(这是当前的行为,但即使在同一个标​​签已经存在)
  • 单独创建一个TagLink条目时标签已经存在

我想到了两个解决方案:

  • 以某种方式覆盖Tag的创建方法来检查是否存在,然后手动创建TagLink条目(如果存在)。如果不是,则默认继续。
  • 使用〜全部CRUD URI公开标签列表(/tags),然后强制使用/{items,users}/:id/tags上的标签ID。

理想情况下,我更喜欢第一个,因为它更透明,使API更平滑。

所以,任何线索都会受到欢迎!

回答

1

我最终做了第一个解决方案,这很容易。这个想法是在引导脚本中替换User.create方法,该引导脚本找到具有相同text的标签,并在找到该标签时将其返回。

module.exports = function(app) { 
    var Tag = app.models.Tag; 

    // Override Tag.create to avoid duplicates 
    Tag.createRaw = Tag.create; 
    Tag.create = function(data, token, cb) { 
     // Find matching tag 
     Tag.findOne({where: {text: data.text}}, (err, tag) => { 
      if (err)  cb(err); 
      // If the tag is found, return it 
      else if (tag) cb(null, tag); 
      // Else create it 
      else   Tag.createRaw(data, token, cb); 
     }); 
    } 
}