如何在CouchDB中实现唯一键约束

时间:2017-12-18 00:09:21

标签: node.js nosql couchdb domain-driven-design clean-architecture

我使用CouchDB,我希望所有用户都能收到独特的电子邮件。当我尝试复制电子邮件时,我希望数据库返回状态400(错误请求)。

但是由于没有办法在CouchDB中定义约束,我应该自己实现它,我的问题是:

我的应用程序的哪一层应符合此规则?

(1)域对象层
  我真的不知道如何在这一层实现它

(2)交互层
    这种约束可以在这里的交互者中实现,因为存在业务规则所在的位置。但如果单个文档有多个规则,可能会增加不必要的复杂性......

function createUser(userData)  {
  let email = userData.email;
  let exist = await userDB.userExist(email);

  if(exist) {
    // return status 400
  } else {
    // create user
  }    
}

(3)数据库网关层
   约束也可以在数据库网关层中实现。通常我们会为每个特定实体提供一个网关。但这是否意味着外部服务适配器包含一些业务逻辑?

class userDB()  {
  constructor(opts) {
    this.db = opts.db.connect();
  }

  async userExist(email) {
    return await this.db.fetchByView('email', email);
  }

  async create(email) {
    let exist = await this.userExist(data.email);
    if(exist) {
      // throw error
    } else {
      // create the user
    }
  }
}

2 个答案:

答案 0 :(得分:2)

Unique email address is a very old DDD topic. It relates to the set validation. The simplest (and from my point of view is also the best) is to place a constraint at the database level.

From what I know, the only whay to create an unique constraint in CouchDB is to use the _id field so you can use this solution. This idea is to put the email in the _id field.

let exist = await this.userExist(data.email);

if(exist) { // throw error } else { // create the user }

This method is not safe for concurrent updates. Two users can be created at the same time. Imagine that for both the requests the this.userExist(data.email) is returning false.

答案 1 :(得分:1)

我不是CouchDB专家,但从纯粹的清洁架构角度来看,确保唯一的电子邮件地址是一个应该在交互器中实现的业务规则。

使用这种方法,即使你曾经决定用其他一些细节 - 另一个存储系统替换细节CouchDB,你的业务规则也会保持不变。