Building relational meteor databases for hierarchical structures

Hey there, I'm diving into the world of Meteor and Mongo and I've got some basic questions on designing databases.

Imagine I'm creating a turn-based strategy game similar to Advance Wars. I'm stuck on how to structure my data efficiently.

I put together a little demo in my html:

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

For this, I have a helper set up on Template.body:

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

Now, everything seems fine when running just one game. But handling multiple games concurrently is where I hit a roadblock.

One solution could involve having a Games collection wherein each Game links two or more Players, each with their own list of Characters. Each Character would then hold an x and y position. But I'm unsure about querying after replacing Characters.find({}).

Possibly something like

Game.findOne({game_id: game_id}).players[player_id].characters
could work. However, I'm not clear on the performance implications. Will Meteor fetch the entire game object every time a character moves?

Another option that requires minimal changes might be

Characters.find({game_id: 123, player_id: 1})
. This way, all Characters from all games are stored in one large collection. Though it feels odd not encapsulating Characters under a specific Game, maybe this approach is more practical.

After jotting down those thoughts, the second option seems more logical. I'd probably define other internal game objects as separate collections. Does this sound like a good plan to tackle this issue?

Answer №1

Imagine your collection contains items that have the following structure:

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

If you have the _id of a specific game and you want to retrieve all the players along with their characters, you can simply do the following:

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

Once you have the games, you will be able to iterate over a single element, which is the game you selected using its unique ID.

In your template, you can then display this information as follows:

<div class="games">
  {{#each games}}
    <h1>{{started}} — The game's `started` property.</h1>
    {{#each players}}
      <div class="player" id="{{_id}}">
        <h2 id="{{_id}}">{{name}} — Player's Name</h2>
        {{#each characters}}
          <h3 id="{{_id}}">{{x}}, {{y}} — Character's Coordinates</h3>
        {{/each}}
      </div>
    {{/each}}
  {{/each}}
</div>

Take note of how _id is used based on the current context.

Alternatively, you can achieve the same result by using a plain object instead of a cursor, but only when you are certain that the query will return a single element:

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

The template structure will vary in this case. Since you have a single plain object, there is no need for iteration. You can access the properties directly within a with block:

<div class="game">
  {{#with game}}
    <h1>{{started}} — Game's `started` property</h1>
    {{#each players}}
      <div class="player" id="{{_id}}">
        <h2 id="{{_id}}">{{name}} — Player's Name</h2>
        {{#each characters}}
          <h3 id="{{_id}}">{{x}}, {{y}} — Character's Coordinates</h3>
        {{/each}}
      </div>
    {{/each}}
  {{/with}}
</div>

Ensure that your template (or client side) is subscribed to the Games collection, and that this collection is published on the server providing the complete field set without querying unnecessary data.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Issue with Jquery Drag and Drop functionality, navigate to a different page

I am trying to incorporate a page with js from quotemedia.com using Jquery. When I insert the js into the sortable, and then drag and drop the element containing the js, it suddenly switches to full page display. This issue occurs in Firefox, but IE works ...

Having difficulty managing asynchronous Node JS API requests

I'm a beginner in Node.js and I've taken on a project that involves querying both the Factual API and Google Maps API. As I put together code from various sources, it's starting to get messy with callbacks. Currently, I'm facing an issu ...

Unable to modify the hover color on the image or icon

After creating a circle icon with an image in the center, I wanted to make the image change colors on hover. The main focus of the icon is the circle itself. In my attempt to achieve this effect, I included the following code for the circle icon: .circle- ...

The GraphQL MongoDB integration with Mongoose is experiencing an issue where the populate field is not

I have implemented GraphQL MongoDB Mongoose in my project, where I have defined 2 collections - users and categories. Category.js const mongoose = require('mongoose'); const Schema = mongoose.Schema; const categorySchema = new mongoose.Schema({ ...

Error: jquery unexpectedly encountered a token 'if'

I've successfully created an autocomplete suggestion box, but I'm facing an issue when using if and else along with console.log(). An error is displayed in my console saying Uncaught SyntaxError: Unexpected token if, and I'm not sure why. Ho ...

The JavascriptExecutor in Selenium with Java is experiencing issues and is not functioning properly for Firefox version 24.0

In a few of my test cases, I've been using the following command because it's quite useful when trying to click on a hidden element that only appears when hovered over some context: ((JavascriptExecutor)driver).executeScript("$('selector_fo ...

Sort by label using the pipe operator in RxJS with Angular

I have a situation where I am using an observable in my HTML code with the async pipe. I want to sort the observable by the 'label' property, but I'm not sure how to correctly implement this sorting logic within the pipe. The labels can be e ...

Does the built-in waiting mechanism in Protractor automatically handle promises?

While browsing through Stack Overflow, I stumbled upon this response in a discussion about Protractor tests and asynchronous solutions: 'AFAIK expect waits internally for the related promises.' I have tried looking through the official Protract ...

Issue with reflect metadata in Next.js edge runtime causing functional problems

Currently, I am utilizing a package in my upcoming 13 app that incorporates reflect metadata. Unfortunately, during the next build process, an error occurs for which I haven't been able to find a solution. ../../eshop-sdk-js/node_modules/reflect-metad ...

Babeljs encountered an error: TypeError - The super expression should be a function or null, not undefined

Currently, my project involves implementing multiple-files inheritance in ES6 using Node.js and Babel. Babel is used to convert the ES6 code to ES5 since Node does not fully support ES6 yet. Import/export statements are used to connect the different files ...

(discovered: [object Promise]) utilizing Material UI and DexieJS

Exploring DexieJS and Material UI for the first time has been quite a learning experience, so I may have overlooked a crucial aspect. Here is a glimpse of my code: Subscreen.tsx const [fightersArray, setFightersArray] = useState<FighterEntity[]>([]) ...

I'm curious if there is an eslint rule specifically designed to identify and flag any unnecessary spaces between a block comment and the function or

Can anyone help me find a solution to prevent the following issue: /** * This is a comment */ function foo() { ... } I need it to be corrected and formatted like this: /** * This is a comment */ function foo() { ... } ...

Jest does not support util.promisify(setTimeout) functionality

While I understand there may be similar questions on SO, I believe mine is unique and hasn't been addressed in the current answers. I'm currently experimenting with testing a REST API in Express.JS. Below, you'll find a basic working exampl ...

``Passing a database value from a controller to a table popup through AJAX: A step-by

I need to display a popup containing data from a database. I'm using an AJAX function with onclick() to achieve this. The data retrieved will be shown in the popup, which includes a table. However, I'm unsure how to properly display the data with ...

The ID update functionality in Node.js is malfunctioning

Hello everyone, I am currently venturing into the world of NodeJS with a goal to create a backend API for a car rental agency. After writing some code to update, view, and delete records by id stored in MongoDB, I encountered a strange issue where it only ...

Stop RequireJS from Storing Required Scripts in Cache

It seems that RequireJS has an internal caching mechanism for required JavaScript files. Whenever a change is made to one of the required files, renaming the file is necessary in order for the changes to take effect. The typical method of adding a version ...

"Troubleshooting: Why is the 'RectAreaLightHelper' not moving correctly in React-three-fiber

Issue Overview: I have noticed that the rectAreaLight behaves differently compared to other light helpers in my project. Despite using the "useHelper" function and placing it in the "three/examples" folder, the position of the rectAreaLight does not change ...

Galleriffic 2.0: Enhancing Animation Queues

I'm currently exploring how to utilize the stop() function in order to halt the animation buildup within Galleriffic. This issue arises when swiftly and repeatedly mousing over the thumbnail images. While I understand that in a basic jQuery script, yo ...

Utilizing the Fetch API to retrieve a Flickr feed in JSON structure

When interacting with the flicker feed API, I have successfully received a JSON response using $.getJSON. However, when attempting to use Fetch instead, only an XML response seems to be retrieved. Example of working with $.getJSON: var flickerAPI = "http ...

The functionality of $watch in AngularJS is not meeting the desired outcomes

Within my controller, I am looking to receive notifications when the value of a certain variable changes. Specifically, I want a function to be triggered whenever this variable is updated. To achieve this, I am utilizing the $watch method in AngularJS. Her ...