1

这是我在 stackoverflow 上的第一个问题,所以我希望我遵循正确的协议。

我正在创建一个基于 CouchDB 和 NodeJS 的基本浏览器游戏。在我的游戏中,用户可以拥有多个角色。我决定在数据库中将玩家与他们的角色分开,因为我很少需要将用户帐户数据(电子邮件、真实姓名等)与他们的角色数据相关联。无论如何,这是我的问题:

我希望能够创建一个视图,该视图返回由玩家控制的所有角色。本文档中将有一个名为“所有者”的属性。我认为最简单的方法是创建一个视图,该视图返回按所有者分类的所有角色的列表。

到目前为止,这是我的代码:

功能(文档){发出(文档所有者,文档);}

我试图得到这样的结果(注意,这是简化的;我知道 CouchDB 在输出中包含其他数据):

{
    "player1":{
        "character1":{
            "data":{}
        },
        "character2":{
            "data":{}
        }
    },
    "player2":{
        "character1":{
            "data":{}
        },
        "character2":{
            "data":{}
        }
    }
}

键必须是唯一的吗?我的代码会给我想要的结果吗?

我不赞成分离数据的想法,我也可以将字符放在用户文档下并创建两个视图,一个只发出用户帐户数据并省略字符数据,另一个只发出字符数据并省略用户数据,但这对我来说似乎有点尴尬。我宁愿将数据分开,因为我可能需要编写特定于角色数据的其他视图,而且如果我将角色与数据库中的玩家分开,似乎会更好地组织起来。

在相关说明中,有没有办法通过传入第二个参数来过滤响应?我认为这会否定视图的效率,并且在这种情况下我可能应该使用临时视图。我的问题是,这个视图可能会返回大量数据(实际上是整个数据库),通过 HTTP 传输时可能会非常慢,尤其是因为我不需要大部分数据。

另一种可能的解决方案是将用户控制的每个字符的 _id 作为属性存储在用户帐户数据库中。这对我来说似乎很明智,但如果有不同的,或者我敢说“更好”的选项可用,那么我很想听听。

这个问题的最佳解决方案是什么?

非常感谢您的帮助。

4

1 回答 1

4

你在正确的道路上。如果你想用 Reduce 来做这个,你可以定义这个 Map:

function(doc) { 
  var r = {}, c = {}; 
  c[doc._id] = doc;
  r[doc.owner] = c; 
  emit(doc.owner,r); 
}

而这个减少:

function(k,v,red) {
  var r = {};
  for (var i in v) {
    for (var owner in v[i]) {
      if (!(owner in r)) r[owner] = {};
      for (var character in v[i][owner])
        r[owner][character] = v[i][owner][character];
    }
  }
  return r;
}

这应该直接返回您所要求的,但几乎不是最优的:视图必须为 Map 和 Reduce 部分存储大量数据......

相反,我会选择没有 Reduce 的 Map,如下所示:

function(doc) {
  emit(doc.owner,null);
}

使用 查询此地图时include_docs=true,将返回如下所示的行:

[  
  { id : 'charid', key : 'playid', doc : { /* character document */ } },
  ...
]

key服务器负载较轻,如果您确实需要,您仍然可以通过使用结果中的玩家重新组合角色。结果按 排序key,然后按 排序id

startkey您可以使用和endkey都等于玩家标识符来查询此视图,以获取玩家拥有的所有角色。如果您只需要字符标识符,则添加并且不会发送include_docs=false重的部分。doc

于 2010-12-13T11:09:05.920 回答