我可以通过公共密钥订购CouchDB文档吗?

时间:2010-12-13 07:09:38

标签: database-design nosql couchdb serverside-javascript

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

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

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

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

  

功能(DOC){       emit(doc.owner,doc);   }

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

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

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

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

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

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

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

非常感谢您的帮助。

1 个答案:

答案 0 :(得分: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部分存储大量数据......

相反,我会选择不减少的地图,如下所示:

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

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

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

服务器负载较轻,如果确实需要,您仍然可以使用结果中的key重新组合播放器中的字符。结果按key排序,然后按id排序。

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