Velo: Working with the Data API

Visit the Velo by Wix website to onboard and continue learning.

Introduction

The Wix Data API lets you work with your database collections using code and gives you more capabilities than what is available in the editor alone.

To learn more about managing your data without using the Data API and how the database is structured, see About Database Collections.

Wix Data includes functions that enable you to manage the data in existing collections, build queries on collections, and register hooks on different operations.

With the Collections API you can create new collections and manage their structure.

Important:

  • You must first create a collection either in the CMS or by using the Collections API before you can work with it using the Wix Data API.

  • To use the Wix Data API, you need to import the module as follows:

    Copy
    1
    //Add the following to the top of your code to import wixData:
    2
    import wixData from 'wix-data';

Wix Data API

The Wix Data API allows you to manipulate the data in your collections and retrieve it in meaningful and useful ways. It contains:

  • wix-data: Functions that let you query and manipulate the data in your collections.
  • Hooks: Code you can set to run before or after you interact with a collection. Hooks are added to a collection in the Velo sidebar (Wix Editor) or CMS panel (Wix Studio) when you hover over the collection name. The code for the hooks are written in the data.js file which resides in the backend.
  • WixDataFilter: Functions for filtering a WixDataQuery.
  • WixDataQuery: An object that contains a query definition and functions that enable you to refine a query.
  • WixDataQueryResult: An object that contains a query's results, other information about the query, and pagination methods.
  • WixDataSort: Functions for sorting a WixDataQuery.

Note: Wix places quotas on data requests made by your site, as well as the amount of data your site can contain. These quotas affect the number of requests your site can make per minute and the amount of time your requests can run for.

Let's say you are building a database of customers who have registered on your online jewelry store. Your registration form would collect basic personal information about each customer. It might also ask customers for other information, such as relatives they may shop for, so you could know when to send them notifications of special offers and sales. You may also want to know about their general interests so that you can provide better purchase suggestions. When a customer makes a purchase, you would save the details of their purchase as well.

An item in your collection may look like this:

Copy
1
let newCustomer = {
2
name: "Mary",
3
age: 47,
4
_id: "mary.jones@myemail.com",
5
phone: "(345)123-4567",
6
pic: "Mary.jpg",
7
labels: ["female", "adult", "hiking"],
8
relatives: ["husband", "daughter"],
9
purchases: [
10
{item: "watch", material: "gold", price: "2000.00"},
11
{item: "ring", material: "platinum", price: "500.00"},
12
{item: "bracelet", material: "silver", price: "250.00"}
13
]
14
};

You would then add this item to your collection with the insert method:

Copy
1
wixData.insert("Customer", newCustomer);

As your customer list grows and your site has more traffic, as well as repeat visits from customers, you would use save(), update(), remove(), and get() to modify the items in your collection.

It is important to familiarize yourself with the Wix Data model and query() methods so that you can use the most effective data modeling when you create your collections.

Working with Permissions in Wix Data

When you use Wix Data methods in your Public and Pages files you need to consider the permissions your site visitors will have. Some methods modify data in collections while other methods only read data. Your site visitor needs to have the corresponding permissions for these methods to work. If a method is called with insufficient permissions the method will fail. For more information, see About Database Collection Permissions.

By default, your site visitor's permissions apply to Wix Data methods you call from your backend code also. However, you can call Wix Data methods from backend code without checking permissions by passing the method the WixDataOptions object as the options parameter with the property:value pair suppressAuth: true.

Working with Hooks in Wix Data

The wix-data module contains hooks that allow you to run code before or after you interact with a collection. See How to Use Data Hooks to learn more.

When a method is called in your code, the system first checks that the method was called with the correct permissions. If you registered hooks to a method, they will run only if the method passes the permissions check.

You can call Wix Data methods from the backend without their registered hooks by passing the options parameter for the method a WixDataOptions object with the property:value pair suppressHooks: true.

Querying Your Collection

A collection of data is only useful if you can retrieve the data in meaningful ways. To query a collection, use the query method.

By default, query returns the first 50 items in a collection in descending order of their _createdDate value. For example, the following query logs to the console the first 50 items in the Customer collection, sorted in descending order of their _createdDate values:

Copy
1
wixData.query("Customer")
2
.find()
3
.then( (results) => {
4
console.log(results.items);
5
} );

The find() function is chained to the query, and it runs the query. The find() function returns a Promise that resolves to a WixDataQueryResult object. Because find() returns a Promise, then() is also chained to the query to display the results.

To display the items that the query returns, use the items property of the WixDataQueryResult object.

Refining Your Query

To refine the results of a query, chain WixDataQuery methods to the query. For example, let's say you want to query the Customer collection for all customers over the age of 20. You would chain the gt() (greater than) function to the query, like this:

Copy
1
wixData.query("Customer")
2
.gt("age", 20)
3
.find()
4
.then( (results) => {
5
console.log(results.items);
6
} );

The query() function returns a WixDataQuery object, which contains the definition of the query. Each WixDataQuery method also returns a WixDataQuery object. Since they both return the same type of object, you can chain multiple WixDataQuery methods onto a call to query(), which further refines the query results.

For example, let's say you want to take the results of the previous query, but return only the male customers. You would add the hasSome method to your query, with labels as the paremeterName and Male as the value:

Copy
1
wixData.query("Customer")
2
.gt("age", 20)
3
.hasSome("labels", "Male")
4
.find()
5
.then( (results) => {
6
console.log(results.items);
7
} );

This adds the gt() and hasSome() conditions to the query definition that is stored in the WixDataQuery object. Now when you call find(), it uses these conditions to run the query.

Query Results

Query results are returned in a WixDataQueryResult object. This object has the following properties:

  • currentPage: The index (zero-based) of the current results page number.
  • items: An array that holds the results of the query.
  • length: The number of items in the current results page.
  • pageSize: The query page size, based on the defined limit.
  • query: The WixDataQuery object used in the query.
  • totalCount: The total number of items that match the query.
  • totalPages: The total number of pages the query produces, based on the defined skip and limit values.

For example, the following would display the number of results for the query for male customers over the age of 20:

Copy
1
wixData.query("Customer")
2
.gt("age", 20)
3
.hasSome("labels", "Male")
4
.find()
5
.then( (results) => {
6
console.log(results.totalCount);
7
} );

Pagination

WixDataQueryResult has next() and prev() functions that enable you to easily page forward and backward in your results.

For example, let's say you want to filter the Customer collection for all female customers 20 years or older who have purchased a ring. You also want each page of results to display 15 items. You use the limit method to limit the number of results a query returns.

Copy
1
let femaleRingTwenty;
2
3
wixData.query("Customer")
4
.ge("age", 20)
5
.hasSome("labels","Female")
6
.eq("purchases.item", "ring")
7
.limit(15)
8
.find()
9
.then( (results) => {
10
console.log(results.items);
11
femaleRingTwenty = results;
12
} );

This displays the first 15 results from the query, starting at the first result and ending at the 15th.

To display the next page of results, you would call next on the results:

Copy
1
femaleRingTwenty.next()
2
.then(function(results) {
3
console.log(results.items);
4
femaleRingTwenty = results;
5
} );

The next() function also returns a Promise, so you chain then() to the call to next and log the resolution of the Promise to the console, which returns the 16th through 30th results. Also, assign femaleRingTwenty the results of next() so that you can call prev() or next() on femaleRingTwenty to get the previous or next page of results.

Manual Pagination with Prev and Next

The skip() function enables next() and prev() to provide a page of query results that skips the first number of results from the total results that match the query. For example, when you query the collection in the pagination example above, it returns results with a limit() of 15, but it also has a default skip() value of 0. This returns the query results starting at the 1st result and ending at the 15th.

When you then call next() for the first time, it returns results with a skip() value of 15 and a limit() of 15. This tells Wix Data to return the query results starting at the 16th result and ending at the 30th result. If you call femaleRingTwenty.next() again, it returns results with a skip() value of 30 and a limit of 15, returning results starting at the 31st result and ending at the 45th. When you call prev() and next(), they handle changing the skip() value to match the requested range of results.

You can also manually assign a value to skip(). This would be useful if you want to enable jumping to a specific page of results without having to use next() or prev() multiple times. For example, using the query in the previous example, if you want to get the 5th page of results with 12 results per page, you would query your collection with a skip of 48 (limit * (5-1)) and a limit of 12:

Copy
1
let queryResults;
2
3
wixData.query("Customer")
4
.ge("age", 20)
5
.hasSome("labels","Female")
6
.eq("purchases.item", "ring")
7
.skip(48)
8
.limit(12)
9
.find()
10
.then ( (results) => {
11
console.log(results.items);
12
queryResults = results;
13
} );

This logs the 49th through 60th results. If you then call next() or prev() on queryResults, they return the next or previous 12 results.

Date Fields

Wix Data supports 2 kinds of date fields:

  • Date and Time
  • Date

These kinds of fields have different data types and should be used differently in your code.

Date

Date fields are represented as strings in ISO 8601 date format (YYY-MM-DD). When you retrieve an item with this kind of field, or write to one, you should use this format. 

Date and Time

Date and Time fields are represented as JavaScript Date objects. When working with this type of field, you should use this format. If you assign a Date and Time field a value of an ISO date string, Wix Data treats it as it would any other string.

For example, you can use a JavaScript Date object as the value for a Date and Time field when creating a new Wix Data item. In this example, birthday is assigned a date:

Copy
1
let newCustomer = {
2
name: "Mary",
3
age: 47,
4
_id: "mary.jones@myemail.com",
5
pic: "Mary.jpg",
6
labels: ["Female", "Adult", "Hiking"],
7
relatives: ["husband", "daughter"],
8
birthday: new Date(1975, 10, 5)
9
};
10
11
// Use wixData.insert to add a new item to the Customer collection
12
let entry = wixData.insert("Customer", newCustomer);

Wix Data always saves Date objects and displays them in the console as a string with a UTC timezone. For example, if you display the results of the previous insert:

Copy
1
entry.then( (results) => {
2
console.log(results);
3
} );

  it logs:

Copy
1
{
2
name: "Mary",
3
age: 47,
4
_id: "mary.jones@myemail.com",
5
pic: "Mary.jpg",
6
labels: ["Female", "Adult", "Hiking"],
7
relatives: ["husband", "daughter"],
8
birthday: "1975-10-05T14:24:20Z",
9
_createdDate: "2004-04-01T01:04:45Z",
10
_UpdatedDate: "2006-02-15T12:35:20Z",
11
}

If you need to convert one type of date data to the other, you can do the following.

To convert ISO date strings to Date objects:

Copy
1
const dateString = "1985-11-23";
2
const dateObject = new Date(dateString);

To convert a Date object into an ISO date string:

Copy
1
const dateString = dateObject.toISOString().substring(0,10);
Was this helpful?
Yes
No