Building the Query

See the API reference for a list of available query builder methods.

With our models already set up, it's time to start using them!

Retrieving a List of Records

See the API reference

Let's start initializing a model and building a simple query that gets all records from the database. To achieve this, we can use the get method or its alias all.

We can get a list of posts using the Post model:

const posts = new Post().get()
GET /posts
[
  /* ... */
  {
    id: 1,
    title: 'Post 1',
    text: 'Some text here...',
    user: {
      id: 1,
      firstName: 'Joe',
      lastName: 'Doe'
    }
  },
  {
    id: 2,
    title: 'Post 2',
    text: 'Some text here...',
    user: {
      id: 2,
      firstName: 'John',
      lastName: 'Doe'
    }
  }
  /* ... */
]

Just for convenience, it's possible to make Static calls. We are going to use this approach from now on:

const posts = await Post.get()
GET /posts
[
  /* ... */
  {
    id: 1,
    title: 'Post 1',
    text: 'Some text here...',
    user: {
      id: 1,
      firstName: 'Joe',
      lastName: 'Doe'
    }
  },
  {
    id: 2,
    title: 'Post 2',
    text: 'Some text here...',
    user: {
      id: 2,
      firstName: 'John',
      lastName: 'Doe'
    }
  }
  /* ... */
]
It's also possible to use $get method or its alias $all , which handle and unwrap responses within "data".

Retrieving a Single Record

To retrieve a single record from the database, we can use two methods:

  • first - Get the first record of a list of records.
  • find - Find a specific record in the database.

Getting the First Record

See the API reference

Let's start using first. This method will internally use get to retrieve a list of records and then return the first one.

To get the first Post of a list:

const posts = await Post.first()
GET /posts
{
  id: 1,
  title: 'Post 1',
  text: 'Some text here...',
  user: {
    id: 1,
    firstName: 'Joe',
    lastName: 'Doe'
  }
}
It's also possible to use $first method, which handle and unwrap responses within "data".

Finding a Specific Record

See the API reference

Different from first, the find method wil request a specific record from the database. An identifier must be passed as argument.

To find a specific Post:

const posts = await Post.find(1)
GET /posts/1
{
  id: 1,
  title: 'Post 1',
  text: 'Some text here...',
  user: {
    id: 1,
    firstName: 'Joe',
    lastName: 'Doe'
  }
}
It's also possible to use $find method, which handle and unwrap responses within "data".

Filtering

One of the most important parts when building a query is filtering, so let's get started!

There are two methods we can use to filter our queries:

  • where - Evaluate a value against the column.
  • whereIn - Evaluate multiple values against the column.

We can use these methods as many times as we want.

Evaluating a Single Value

See the API reference

The where method can be used to filter the query by evaluating a value against the column. The first argument is the name of the column, and the second argument is the value to evaluate.

We can filter our Posts to only get results where status is published:

const posts = await Post.where('status', 'published').get()
GET /posts?filter[status]=published

Nested Filter

Available in version >= v1.8.0

The first argument of where also accepts an array of keys, which are used to build a nested filter.

So we can filter our Posts to only get results where status of user is active:

const posts = await Post.where([
  'user', 'status'
], 'active').get()
GET /posts?filter[user][status]=active

Using an Object

Available in version >= v1.10.0

Now is also possible to pass an object.

const posts = await Post.where({
  status: 'published',
  user: {
    status: 'active'
  }
}).get()
GET /posts?filter[status]=published&filter[user][status]=active

Evaluating Multiple Values

See the API reference

The whereIn method is similar to where, but it accepts multiple values instead of a single one. The first argument is the name of the column, and the second argument is an array of values to evaluate.

We can filter our Posts to only get results where status is published or archived:

const posts = await Post.whereIn('status', [
  'published', 'archived'
]).get()
GET /posts?filter[status]=published,archived

Nested Filter

Available in version >= v1.8.0

The first argument of whereIn also accepts an array of keys, which are used to build a nested filter.

So we can filter our Posts to only get results where status of user is active or inactive:

const posts = await Post.whereIn(['user', 'status'], [
  'active', 'inactive'
]).get()
GET /posts?filter[user][status]=active,inactive

Using an Object

Available in version >= v1.10.0

Now is also possible to pass an object.

const posts = await Post.where({
  status: ['published', 'archived'],
  user: {
    status: ['active', 'inactive']
  }
}).get()
GET /posts?filter[status]=published,archived&filter[user][status]=active,inactive

Sorting

See the API reference

We also need to sort our queries, so let's do this now!

The method we want to use now is orderBy. The arguments are the names of the properties we want to sort. We can pass as many arguments as we want.

Single Sort

We can sort our Posts by the created_at date:

const posts = await Post.orderBy('-created_at').get()
GET /posts?sort=-created_at

Multiple Sort

And we can sort by their title too:

const posts = await Post.orderBy('-created_at', 'title').get()
GET /posts?sort=-created_at
Sorting is ascending by default and can be reversed by adding a hyphen (-) to the start of the property name.

Using an Array

Available in version >= v1.8.0

The first argument of orderBy also accepts an array of string.

const posts = await Post.orderBy(['-created_at', 'title']).get()
GET /posts?sort=-created_at

Including Relationships

See the API reference

Sometimes, we will want to eager load a relationship, and to do so, we can use the include method or its alias with. The arguments are the names of the relationships we want to include. We can pass as many arguments as we want.

Let's eager load the relationships category and tags of our Post:

const posts = await Post.include('category', 'tags').get()
GET /posts?include=category,tags

Using an Array

Available in version >= v1.8.0

The first argument of include also accepts an array of string.

const posts = await Post.include(['category', 'tags']).get()
GET /posts?include=category,tags

Appending Attributes

See the API reference

We can also append attributes to our queries using the append method. The arguments are the names of the attributes we want to append. We can pass as many arguments as we want.

Let's append the attribute likes and shares of our Post:

const posts = await Post.append('likes', 'shares').get()
GET /posts?append=likes,shares

Using an Array

Available in version >= v1.8.0

The first argument of append also accepts an array of string.

const posts = await Post.append(['likes', 'shares']).get()
GET /posts?append=likes,shares

Selecting Fields

See the API reference

If we only need some fields of the model, we can easily select them using the select method.

If the fields we want to select only belongs to the model, we can pass a list of strings as the arguments. But if we want to select fields of relationships as well, then we need to pass an object.

Fields of the Model

The arguments are the names of the fields we want to select. We can pass as many arguments as we want.

We can select only the title and the text fields of our Post model:

const posts = await Post.select('title', 'text').get()
GET /posts?fields[posts]=title,text

Fields of Relationships

The argument is an object, which the name of the first key is the resource defined in the model class, the name of the other keys are the included relationships, and the values are arrays of fields.

We can select only the name field of the category we have to eager loaded:

const posts = await Post.include('category').select({
  posts: ['title', 'text'],
  category: ['name']
}).get()
GET /posts?include=category&fields[posts]=title,text&fields[category]=name

Paginating

A very important feature is paginating, so let's do it now!

There are two methods we will be using here:

  • page - Set the current page.
  • limit - Set the limit of records per page.

Both methods accept a number as an argument.

Let's say we are at page 1, and we want 20 Posts per page:

const posts = await Post.page(1).limit(20).get()
GET /posts?page=1&limit=20

Conditional

Available in version >= v1.10.0

We may need to add a clause based on a condition, and we can do so by using the when method. The first argument is the flag, and the second argument is the callback with the clause we want.

const search = 'foo'
const posts = await Post.when(search, (query, value) => query.where('title', value)).get()
GET /posts?filter[title]=foo

Applying Custom Parameters

See the API reference

We may also need to use parameters that are not provided by vue-api-query, and that's when the params method comes in to help.

The argument is an object of the parameters to add to the query.

const posts = await Post.params({
  doSomething: 'yes',
  process: false,
  multiple: ['awesome', 'amazing', 'super']
}).get()
GET /posts?doSomething=yes&process=false&multiple=awesome,amazing,super

Calling a Custom Resource

See the API reference

In some situations we may also need to define a custom resource endpoint for our model directly in the query. We can override the default resource dynamically by calling the custom method.

Defining a Static Resource

If the custom resource is static, you can simply pass the string as an argument.

We can change the Post resource to get the latest Posts:

const posts = await Post.custom('posts/latest').get()
GET /posts/latest

Defining a Dynamic Resource

But it's also possible to build dynamic resource endpoints with hierarchies, by supplying the arguments in the correct order. It accepts models and strings as arguments. If a model is passed, the model's resource will be used, as well as its primary key's value if available.

We can build a resource to get the latest Posts that belongs to a User:

const user = await User.find(1)
const posts = await Post.custom(user, post, 'latest').get()
GET /users/1
GET /users/1/posts/latest

Configuring the Request

Available in version >= v1.8.0

See the API reference

The config method can be used to configure the current request at query builder. We can pass any config available from the HTTP Instance. If we are using Axios, we should pass an AxiosRequestConfig.

We can add headers, change the method, anything we want:

await Post.config({ headers: { /*...*/ } }).get()

Needless Parent Request

One thing to note is that in some cases we may not need to make a request to parent to build the query we want. If we already know the model's ID, we just need to initialize the model instance with the ID, instead of use find.

We can get a list of Posts that belongs to an User:

const user = new User({ id: 1 })
const posts = user.posts().get()
GET /users/1/posts

And the same thing can be done if we want to define a dynamic resource.

We can create a new User instance with the ID:

const user = new User({ id: 1 })
const posts = await Post.custom(user, post, 'latest').get()
GET /users/1/posts/latest

Mixing Everything Up

Let's mix everything we have learned so far!

We can get a list of latest Posts, where status is published, include the category relation, append likes attribute, select title and text fields, order by created_at, paginate and custom parameters:

const user = new User({ id: 1 })
const posts = await Post
  .where('status', 'published')
  .include('category')
  .append('likes')
  .select('title', 'text')
  .orderBy('-created_at')
  .page(1)
  .limit(20)
  .params({ process: false })
  .custom(user, post, 'latest')
  .get()
GET /users/1/posts/latest
?filter[status]=published
&include=category
&append=likes
&fields[posts]=title,text
&sort=-created_at
&page=1
&limit=20
&process=false