我可以通过公共键来订购 CouchDB 文档吗?

发布于 2024-10-07 07:13:03 字数 1163 浏览 5 评论 0原文

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

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

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

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

函数(文档){ 发出(doc.owner, doc); }

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

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

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

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

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

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

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

预先非常感谢您的帮助。

This is my first question here on stackoverflow, so I hope that I am following the correct protocol.

I am creating a basic browser game based on CouchDB and NodeJS. In my game, users can have multiple characters. I've decided to separate the players from their characters in the database because I rarely need to associate user account data (email, real name, etc) with their character data. Anyway, here's my problem:

I want to be able to create a view which returns all of the characters that are controlled by a player. There will be a property called "owner" in this document. I figure that the easiest way to do this is to make a view which returns a list of all of the characters categorized by owner.

Here's my code so far:

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

I'm trying to get a result like this (note, this is simplified; I know CouchDB includes other data in the output):

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

Do keys have to be unique? Will my code give me the desired result?

I'm not married to the idea of separating the data, and I could alternatively just put the characters under the user document and just create two views, one that would emit just the user account data and omit the character data and another to emit just the character data and omit the user data, but that seems a little awkward to me. I would rather keep the data separate because I may need to write other views specific to the character data, and it seems like it would be better organized if I separated the characters from the players in the database.

On a related note, is there any way to filter the responses by passing in a second parameter? I assume this negates the efficiency of a view and that I should probably use a temporary view in this instance. My problem with this is that I could potentially have a large amount of data being returned by this view (the entire database in fact), which could be very slow when transferred over HTTP, especially since I won't need most of the data.

Another possible solution is to store the _id of each character a user controls as a property in the user account database. This seems sensible enough to me, but if there is a different, or dare I say "better" option available, then I'd love to hear it.

What would be the best solution to this problem?

Thank you so much in advance for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

音盲 2024-10-14 07:13:03

你走在正确的道路上。如果您希望使用Reduce 来做到这一点,您可以定义这个Map:

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

并且这个Reduce:

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排序。

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

You're on the right path. If you wish to do this with a Reduce, you can define this Map:

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

And this Reduce:

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;
}

This should return directly what you asked for, but is hardly optimal: the view has to store a lot of data for both the Map and Reduce parts...

Instead, I would go for a Map without Reduce, like this:

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

This map, when queried with include_docs=true, would return lines that look like this:

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

The server load is lighter, and you can still regroup the characters by player by using the key in the result, if you really need to. The results are sorted by key, then by id.

You can query this view using startkey and endkey both equal to the player identifier to get all the characters a player has. If you only need the character identifiers, then add include_docs=false and the heavy doc part will not be sent.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文