Using Nuxt Content as a database
In the previous article, I shared a new simple tool that lets Monster Hunter Rise players plan, build, and compare sets. In this article, I'll share how I'm managing the data for that app using Nuxt Content.
An inexpensive and efficient database
Nuxt Content is an inexpensive way of storing and managing structured data for your NuxtJS apps. It allows you to store your data in Markdown, JSON, YAML, XML and CSV formats, and best of all, it lets query these data easily using a MongoDB-like API.
Data structure
Monster Hunter Rise has a wide range of information, from the plants that you can gather to the monsters that you can hunt. The tool that I developed focuses on combining the weapons and equipments that you can build base on your play style so that you can make your hunts easier and more fun.
All the data are stored under the /content
directory and are using the JSON format.
Weapons
The weapons are categorized and stored base on their types (e.g. bow-weapons.json
, charge-blade-weapons.json
, etc.). An example of the structure is:
{
"name": "Kamura Iron Bow I",
"slug": "kamura-iron-bow-i",
"type": "bow",
"slots": [],
"attack": 60,
"element": [],
"affinity": 0,
"defense": 0,
"rarity": 1,
"rampSkills": [
"Attack Boost I",
"Affinity Boost II",
"Defense Boost I"
]
}
Armor pieces
Armors are also categorized and stored base on their types (e.g. arms-armors.json
, chest-armors.json
, etc.). An example of the structure is:
{
"name": "Chainmail Gloves S",
"type": "arms",
"slug": "chainmail-gloves-s",
"skills": [
{
"name": "Botanist",
"slug": "botanist",
"level": 1
},
{
"name": "Defense Boost",
"slug": "defense-boost",
"level": 1
}
],
"slots": [
1,
1
],
"rarity": 4,
"baseDefense": 32,
"fireResistance": 0,
"waterResistance": 0,
"thunderResistance": 1,
"iceResistance": 0,
"dragonResistance": 0
}
Skills
All the skills are stored in skills.json
. An example of the structure is:
{
"name": "Divine Blessing",
"slug": "divine-blessing",
"description": "Has a predetermined chance of reducing the damage you take.",
"level": 3
}
Decorations
All decorations are stored in decorations.json
. An example of the structure is:
{
"name": "Absorber Jewel 1",
"slug": "absorber-jewel-1",
"skill": "Recoil Down",
"skillSlug": "recoil-down",
"level": 1
}
Slugs
You may notice that every item, from weapons to decorations, have the slug
field. This is important and without it, Nuxt Content will ignore the item. Think of the slug
field as the item's unique ID.
Fetching data
Retrieving all data
Retrieving all data of a given resource (e.g. weapon, armor, skill, decoration) is very straightforward since it doesn't require any conditions. Example:
this.$content(resourceName).fetch().then((results) => {
// Do something with the results.
})
Where, resourceName
would be the resource (or table) that you want to query. If I wanted to get all bows I'd pass bow-weapons
since the filename where all the bows are stored is bow-weapons.json
. If I wanted to get all head armor pieces I'd pass head-armors
since the head armors are stored in head-armors.json
.
Filtering
An important feature for a set builder is being able to filter items base on a given criteria. For example, I wanted users to be able to filter armors base on a given skill it has. Nuxt Content uses LokiJS under the hood and as such it provides all, if not most, of the common querying methods that you'll need.
The code below is an excerpt of how I query armors base on a given skill. In this snippet, we use the $containsAny
operator since the skills
property of the armor record is an array of objects.
components/AddArmorModal.vue
let queryBuilder = this.$content(this.resourceName)
const conditions = {}
conditions['skills.slug'] = {
$containsAny: [value]
}
queryBuilder = queryBuilder.where(conditions)
queryBuilder.fetch().then((results) => {
// Do something with the results.
})
You can also use the $contains
operator if the compare value is not an array.
In addition, since the skills
property of an armor is an object, I needed to enable the nestedProperties
option of Nuxt Content. See Nuxt Content options on how I did it for this project.
This has got to be my most favorite feature of Nuxt Content. There are a number of operators that you can use such as $eq
, $ne
, $gt
, $gte
, $lt
, $lte
, $in
, and more so be sure to check out the LokiJS's documentation.
Full-text searching
Another useful feature of Nuxt Content is being able to do full-text search out of the box. In the builder app, users can search for any weapon, armor, or decoration by typing in some keywords. The excerpt below is used for searching a decoration using its name or skill:
components/SetDecorationModal.vue
let queryBuilder = this.$content('decorations')
.where({
level: this.level
})
.sortBy('name')
queryBuilder = queryBuilder.search(keywords)
queryBuilder.fetch().then((results) => {
// Do something with the results.
})
The search
method allows you to do full-text searching on a given field. You probably notice that I didn't explicitly specify the field and that's because I wanted to search using both the decoration's name
and skill
fields.
The search
method only allows searching with one field so if you want to be able to use multiple fields, you'll need specify the fields that you want to search on using the fullTextSearchFields
options. See Nuxt Content options on how I did it for this project.
Nuxt Content options
If you have a field that is an array or an object and you need Nuxt Content to be able to query with it, you'll need to set the nestedProperties
option. See Nuxt Content's nestedProperties option for more info.
If you have more than one fields that you want to be searchable via the search
method, you'll need to set the fullTextSearchFields
option. See Nuxt Content's fulltextsearchfields option for more info.
The excerpt below is based on my app's configuration:
nuxt.config.js
export default {
content: {
fullTextSearchFields: ['name', 'skill'],
nestedProperties: ['skills.name', 'skills.slug', 'elements.type']
}
}
Closing
There are a number of tools that lets you manage data but if you want an inexpensive but powerful alternative for your NuxtJS project, I'd strongly recommend checking out Nuxt Content.
The source code for the app is open-source so check it out!