如何实现noSQL数据库抽象?

How to implement noSQL database abstraction?

我使用 CouchDB,这是一种面向文档的数据库,将数据存储为 JSON 文档。我在后端使用Javascript,所以我可以直接存储JS对象。目前,我在存储在 CouchDB 中的模型和我的域层之间有一个直接映射。我觉得这不是什么好事,因为我完全依赖这个数据库。

例子

我有 2 个实体 usersprojects。 一个用户可以有多个项目,这些模型在数据库中表示为单独的文档:

用户文档

{
  "_id": "1",
  "entity": "user"
}

项目文档
该关系由 属性 user_id.

引用
{
  "_id": "2",
  "entity": "project",
  "user_id": "1",
  "name": "project1"
}

// other project document
{
  "_id": "3",
  "entity": "project",
  "user_id": "1",
  "name": "project2"
}

我的问题是:
我应该在层之间保留这种方便的映射,还是应该创建一个抽象层,将模型从数据库转换为域对象?

更方便的用户域对象示例:

// _id property is replaced by id
// entity property is removed
// projects relations stand in a projects array
{
  id: "1",
  projects: [
   { id: "2", name: "project1"},
   { id: "2", name: "project1"}
  ]
}

注意:我想阅读 Eric Evans 的书 "Domain Driven Design"。也许它可以帮助我了解如何管理此类模型抽象。

恕我直言,这个问题与 DDD 并没有太大关系,但无论如何我都在尝试回答它;-)

我肯定会将数据库对象转换为域对象。原因很简单:如果你改变了底层数据存储,你的对象也会改变,然后你将不得不更新你的 domain 代码以获得 technical 原因。

除此之外,数据库对象包含的内容确实比域感兴趣的内容多。这是摆脱它们的另一个原因:为您的域对象建模,使它们干净,并按照您的期望进行操作。

此外,您希望能够轻松地测试您的域对象。如果它们包含所有数据库的东西,这就会变得不必要地困难。

长话短说:不要在域层中使用数据库对象。

我觉得这个问题涉及到很多DDD。
你挣扎的是聚合体。使用 nosql 数据库,文档应包含聚合。
对同一聚合内的实体使用不同的文档将产生持久化聚合对应于多个文档被存储的效果,这可能会独立失败(导致数据损坏)。
相反,DDD 聚合是您域的事务边界,聚合的持久化必须是原子操作。

关于技术方面的东西,如果依赖于将它们从域模型中删除是很好很干净等等......等等......
但是,如果离开它们会导致更多问题,那么就想办法将它们从域中隐藏起来。所以这取决于域的规模。

有关更多信息,这可能会有所帮助: