【问题标题】:Meteor database design for hierarchical structure分层结构的流星数据库设计
【发布时间】:2017-07-01 19:03:59
【问题描述】:

我是 Meteor 和 Mongo 的新手,我有一些基本的数据库设计问题。

假设我正在制作像Advance Wars 这样的回合制策略游戏。我不确定如何构建我的数据。

我在我的 html 中做了一个小演示:

{{#each chars}}
  <div class='char' style={{get_style}}>
      ...
  </div>
{{/each}}

我在 Template.body 上定义了这个助手:

Template.body.helpers({
  chars: function() {
    return Characters.find({});
  },
  ...
})

当我一次只运行一个游戏时,这很好用。但是当我同时运行多个游戏时,我不确定如何使这项工作。

我想一种方法是拥有一个游戏收藏。这些游戏中的每一个都引用了两个或更多玩家,并且每个玩家都可以有一个角色列表。每个字符可以有一个 x 和 y 位置。但后来我不确定我会用什么查询替换Characters.find({})

我猜它可能类似于Game.findOne({game_id: game_id}).players[player_id].characters。但我不确定那里的性能影响是什么。每次角色移动时,Meteor 会拉下整个游戏对象吗?我真的不明白 Meteor 在幕后做了什么。

我猜另一种需要最小更改的可能性是执行Characters.find({game_id: 123, player_id: 1}) 之类的操作。然后我会将所有游戏中的所有角色都放在一个大集合中。没有将角色“封装”在游戏下对我来说似乎有点奇怪,但也许这是要走的路。

实际上,既然我已经把它写出来了,似乎第二个选项更有意义。而且我想我会将所有其他内部游戏对象定义为单独的集合。这是解决这个问题的好方法吗?

【问题讨论】:

    标签: javascript mongodb meteor nosql


    【解决方案1】:

    让我们假设您的收藏中存储的项目看起来像

    {
      _id: String,
      started: Date,
      players: [{
        _id: String,
        name: String,
        characters: [{
          _id: String,
          x: Number,
          y: Number
        }, {
          // ...
        }]
      }, {
        // ...
      }]
    }
    

    如果您有一个游戏的_id,并且需要获取所有玩家和他们的角色,那么您只需这样做

    let gameId = 'whatever';
    const games = Games.find({
      _id: gameId
    });
    

    之后,在games 中,您有一个光标,可让您遍历单个元素,即您通过其 ID 选择的游戏(设计上是唯一的)。

    然后,在你的模板中,你做

    <div class="games">
      {{#each games}}
        <h1>{{started}} — game's `started` scalar property.</h1>
        {{#each players}}
          <div class="player" id="{{_id}}">
            <h2 id="{{_id}}">{{name}} — player's name</h2>
            {{#each characters}}
              <h3 id="{{_id}}">{{x}}, {{y}} — coordinates of a character</h3>
            {{/each}}
          </div>
        {{/each}}
      {{/each}}
    </div>
    

    注意_id 如何尊重当前上下文。

    另一种方法是使用普通对象而不是游标,但只有在保证查询结果是单个元素的情况下才应该使用它:

    let gameId = 'whatever';
    const game = Games.findOne({
      _id: gameId
    });
    

    模板看起来会有些不同。由于您只有一个普通对象,因此您没有任何东西可以迭代。因此,您可以访问该对象的属性,省略最顶层的上下文并将其替换为 with 块:

    <div class="game">
      {{#with game}}
        <h1>{{started}} — game's `started` scalar property.</h1>
        {{#each players}}
          <div class="player" id="{{_id}}">
            <h2 id="{{_id}}">{{name}} — player's name</h2>
            {{#each characters}}
              <h3 id="{{_id}}">{{x}}, {{y}} — coordinates of a character</h3>
            {{/each}}
          </div>
        {{/each}}
      {{/with}}
    </div>
    

    请确保您的模板(或整个客户端)订阅了Games 集合,并且该集合在服务器上发布并返回整个字段集并且不查询数据(或者它确实但你可以控制它)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-17
      • 1970-01-01
      • 2015-03-12
      相关资源
      最近更新 更多