Rest-full API

Once you have defined a model, then you can use create, read, update, and delete (CRUD) operations to add data to the model, manipulate the data, and query it. All LoopBack models that are connected to persistent data stores (such as a database) automatically have the create, retrieve, update, and delete operations of the PersistedModel class.

Operation REST LoopBack model method (Node API)* Corresponding SQL Operation
Create PUT /modelName
POST /modelName
create()* INSERT
| Read (Retrieve) GET /modelName?filter=… find()* SELECT
| Update (Modify) POST /modelName
PUT /modelName
updateAll()* UPDATE
| Delete (Destroy)DELETE /modelName/modelID destroyById()* DELETE

(*) Methods listed are just prominent examples; other methods may provide similar functionality; for example: findById(), findOne(), and findOrCreate(). See PersistedModel API documentation for more information.



Create Simple API

Create models

first we are going to create a CoffeeShop model that will automatically have REST API endpoints.
Go into your new application directory, then run the LoopBack model generator:

$ cd flashboard

$ slc loopback:model

The generator will prompt for a model name. Enter CoffeeShop:

[?] Enter the model name: CoffeeShop

It will ask if you want to attach the model to any data sources that have already been defined.
At this point, only the default in-memory data source is available. Press Enter to select it:

...
[?] Select the data-source to attach CoffeeShop to: (Use arrow keys)
❯ db (memory)

Then the generator will prompt you for the base class to use for the model. Since you will eventually connect this model to a persistent data source in a database, press down-arrow to choose PersistedModel, then press Enter:

[?] Select model's base class: (Use arrow keys)
  Model
❯ PersistedModel
  ACL
  AccessToken
  Application
  Change
  Checkpoint

PersistedModel is the base object for all models connected to a persistent data source such as a database. See LoopBack core concepts for an overview of the model inheritance hierarchy.
One of the powerful advantages of LoopBack is that it automatically generates a REST API for your model. The generator will ask whether you want to expose this REST API.
Hit Enter again to accept the default and expose the Person model via REST:

[?] Expose CoffeeShop via the REST API? (Y/n) Y

LoopBack automatically creates a REST route associated with your model using the plural of the model name. By default, it pluralizes the name for you (by adding “s”), but you can specify a custom plural form if you wish. See Exposing models over REST for all the details.
Press Enter to accept the default plural form (CoffeeShops):

[?] Custom plural form (used to build REST URL):

Next, you’ll be asked whether you want to create the model on the server only or in the /common directory, where it can potentially be used by both server and client LoopBack APIs. Keep, the default, common, even though in this application you’ll only be working with server-side models:

? Common model or server only?
❯ common
  server

Every model has properties. Right now, you’re going to define one property, “name,” for the CoffeeShop model.
Select string as the property type (press Enter, since string is the default choice):

Let's add some CoffeeShop properties now.
Enter an empty property name when done.
[?] Property name: name
   invoke   loopback:property
[?] Property type: (Use arrow keys)
❯ string
  number
  boolean
  object
  array
  date
  buffer
  geopoint
  (other)

Each property can be optional or required. Enter y to make name required:

[?] Required? (y/N)

Then you’ll be prompted to enter a default value for the property; press Enter for no default value:

? Default value[leave blank for none]:

Then, you’ll be prompted to add another property. Follow the prompts to add a required property named “city.”

Let's add another CoffeeShop property.
? Property name: city
? Property type: string
? Required? Yes
? Default value[leave blank for none]:

End the model creation process by pressing Enter when prompted for the name of the next property.
The model generator will create two files in the application’s common/models directory that define the model: coffee-shop.json and coffee-shop.js.

Important: The LoopBack model generator, automatically converts camel-case model names (for example MyModel) to lowercase dashed names (my-model). For example, if you create a model named “FooBar” with the model generator, it creates files foo-bar.json and foo-bar.js in common/models. However, the model name (“FooBar”) will be preserved via the model’s name property.

Check out the project structure:

For all the details of the canonical LoopBack application structure, see Project layout reference.

First, start the application:

$ npm run service
...
Browse your REST API at http://0.0.0.0:3000/explorer
Web server listening at: http://0.0.0.0:3000/

Note: Running your app with the node command is appropriate when you’re developing on your local machine. In production, consider using API Connect or a process manager for scalability and reliability.

Open your browser to http://0.0.0.0:3000/ (on some systems, you may need to use http://localhost:3000 instead). You’ll see the default application response that displays some JSON with some status information; for example:

{"started":"2017-03-10T21:59:47.155Z","uptime":42.054}

Now open your browser to http://0.0.0.0:3000/explorer or http://localhost:3000/explorer. You’ll see the StrongLoop API Explorer:

Through a set of simple steps using LoopBack, you’ve created a CoffeeShop model, specified its properties and then exposed it through REST.



API Explorer

You’re not the only one who’ll use the API you just created. That means you’ll need to document your API. Fortunately, LoopBack provides API Explorer for you.

Run API Explorer

Note: API Designer Explorer’s functionality is the same as StrongLoop Explorer. The instructions and screenshots below are for the StrongLoop tools.

Run the application:

`$ npm run service

Now go to http://localhost:3000/explorer. You’ll see the StrongLoop API Explorer showing the two models this application has: Users and CoffeeShops:

About LoopBack built-in models

In addition to the CoffeeShop model that you defined, by default Loopback generates the User model and its endpoints for every application.
LoopBack creates several other models for common use cases. For more information, see built-in models .

Exploring the CoffeeShop model

Right now, you’re going to “drill down” on the CoffeeShop model. Click on CoffeeShops to show all its API endpoints:

Scan down the rows of the API endpoints: you can see that they cover all the normal create, read, update, and delete (CRUD) operations, and then some.
Click on the first row, POST /CoffeeShops Create a new instance of the model and persist it into the data source to expand that operation:

Follow the instructions in the diagram above.
Click in Model Schema to get a JSON “data template” that you can edit in the data field.
Add some text for the name property. You don’t have to put anything for the id property, because LoopBack will automatically manage it to ensure there is always a unique ID for each model instance.

{
  "name": "My Coffee Shop",
  "id": 0
}

Then click the Try it out! button.
You’ll see information on the REST request submitted and the application’s response (for example):

The Response Body field will show the data that you just entered, returned as confirmation that it was added to the data source.
Now click on GET /CoffeeShops to expand that endpoint. Click Try it out! to retrieve the data you entered for the CoffeeShop model. You should see the record you created using the POST API.
If you are so inclined, try some other requests: You can enter more complicated queries using the filter field to specify a Where filter, Limit filter, and other kinds of filters on the query. See Querying data for more information.

Tip: API Explorer automatically adds “filter” to the query string, but you must enter Stringified JSON in the filter field. Also make sure that the quotes you use are proper straight quotes ( " ), not curved or typographic quotation marks ( “ or ” ).
These can often be hard to distinguish visually.
You may have noticed the accessToken field and Set Access Token button at the top right of the API Explorer window. Use these to authenticate a user and “login” to an app so you can perform actions that require authentication. For more information, see Introduction to User model authentication.



Creating data (model instances)

Use the following PersistedModel methods to add data, that is to insert or create instances:

  • create - creates a new model instance (record).
  • upsert - checks if the instance (record) exists, based on the designated ID property, which must have a unique value; if the instance already exists, the method updates that instance. Otherwise, it inserts a new instance.
  • findOrCreate - Find one instance matching the filter object provided as the first parameter. If found, returns the object. If not found, creates a new instance (record).
  • Important: Be sure to include a where clause in the filter object. Without the where, the findOrCreate finds and returns the first record in the collection, without error, which can lead to unintended behavior.
  • save - Save model instance. If the instance doesn’t have an ID, then calls create instead. Triggers: validate, save, update, or create.


Updating data (model instances)

Static method (called on the Model object):

Important: The where clause used with updateAll() is slightly different than that for queries. Omit { where : ... }from the where clause. Simply provide the condition as the first argument.
For more information, see Where filter.
Instance methods (called on a single model instance):

Performing bulk updates



Deleting data

Static methods (called on the Model object):

Important:
The where clause with destroyAll() is slightly different than that for queries. Omit { where : ... } from the where clause. Simply provide the condition as the first argument.
For more information, see Where filter.</div>



Querying data

A query is a read operation on models that returns a set of data or results. You can query LoopBack models using a Node API and a REST API, using filters, as outlined in the following table. Filters specify criteria for the returned data set. The capabilities and options of the two APIs are the same–the only difference is the syntax used in HTTP requests versus Node function calls. In both cases, LoopBack models return JSON.

Query Model API (Node) REST API
Find all model instances using specified filters. find(filter, callback)

Where filter is a JSON object containing the query filters.
See Filters below. | GET /modelName?filter…

See Model REST API - Find matching instances.
See Filters below.

Find first model instance using specified filters.findOne(filter, callback)

Where filter is a JSON object containing the query filters.
See Filters below.

GET /modelName/findOne?filter…

See Model REST API - Find first instance.
See Filters below.

Find instance by ID. findById(id, [filter,] callback)

Where optional filter is a JSON object containing the query filters.
See Filters below.

GET /modelName/modelID

See Model REST API - Find instance by ID.

Important: A REST query must include the literal string “filter” in the URL query string. The Node API call does not include the literal string “filter” in the JSON.

LoopBack API Explorer adds “filter” to the query string, but you must enter Stringified JSON in the filter field. Also make sure that the quotes you use are proper straight quotes ( “ ), not curved or typographic quotation marks ( “ or ” ). These can often be hard to distinguish visually.

Tip: If you are trying query filters with curl, use the -g or --globoff option to use brackets [ and ] in request URLs.

LoopBack supports the following kinds of filters:

See Filters below for more information.
Examples
See additional examples of each kind of filter in the individual articles on filters (for example Where filter).
An example of using the find() method with both a where and a limit filter:

Account.find({where: {name: 'John'}, limit: 3}, function(err, accounts) { /* ... */ });

Equivalent using REST:

/accounts?filter[where][name]=John&filter[limit]=3

Filters

In both REST and Node API, you can use any number of filters to define a query.
LoopBack supports a specific filter syntax: it’s a lot like SQL, but designed specifically to serialize safely without injection and to be native to JavaScript. Previously, only the [PersistedModel.find()](http://apidocs.strongloop.com/loopback/#persistedmodel-find) method (and related methods) supported this syntax.
The following table describes LoopBack’s filter types:

Filter type Type Description
fields Object, Array, or String Specify fields to include in or exclude from the response. See Fields filter.
include String, Object, or Array Include results from related models, for relations such as belongsTo and hasMany.
See Include filter.
limit Number Limit the number of instances to return.
See Limit filter.
order String Specify sort order: ascending or descending. See Order filter.
skip (offset) Number Skip the specified number of instances.See Skip filter.
where Object Specify search criteria; similar to a WHERE clause in SQL. See Where filter.

Using “stringified” JSON in REST queries
Instead of the standard REST syntax described above, you can also use “stringified JSON” in REST queries. To do this, simply use the JSON specified for the Node syntax, as follows:

?filter={ Stringified-JSON }

where Stringified-JSON is the stringified JSON from Node syntax. However, in the JSON all text keys/strings must be enclosed in quotes (“).

Important:
When using stringified JSON, you must use an equal sign after ?filter in the query string.
For example: http://localhost:3000/api/books?filter={%22where%22:{%22id%22:2}}
For example: GET /api/activities/findOne?filter={"where":{"id":1234}}

Filtering arrays of objects
The loopback-filters module implements LoopBack’s filter syntax. Using this module, you can filter arrays of objects using the same filter syntax supported by MyModel.find(filter).

Note:
We plan to convert all modules to use loopback-filter, so it will become LoopBack’s common “built-in” filtering mechanism.
Here is a basic example using the new module.

var data = [{n: 1}, {n: 2}, {n: 3, id: 123}];
var filter = {where: {n: {gt: 1}}, skip: 1, fields: ['n']};
var filtered = require('loopback-filters')(data, filter);
console.log(filtered); // => [{n: 3}]


Fields filter

A fields filter specifies properties (fields) to include or exclude from the results.
REST API

filter[fields][_propertyName_]=<true|false>&filter[fields][propertyName]=<true|false>...

Note that to include more than one field in REST, use multiple filters.
You can also use stringified JSON format in a REST query.

Examples
Return only id, make, and model properties:
REST

?filter[fields][id]=true&filter[fields][make]=true&filter[fields][model]=true


Include filter

An include filter enables you to include results from related models in a query, for example models that have belongsTo or hasMany relations, to optimize the number of requests. See Creating model relations for more information.
The value of the include filter can be a string, an array, or an object.

REST API
filter[include][relatedModel]=propertyName You can also use stringified JSON format in a REST query.

REST examples
These examples assume a customer model with a hasMany relationship to a reviews model.
Return all customers including their reviews:

/customers?filter[include]=reviews

Return all customers including their reviews which also includes the author:

/customers?filter[include][reviews]=author

Return all customers whose age is 21, including their reviews which also includes the author:

/customers?filter[include][reviews]=author&filter[where][age]=21

Return first two customers including their reviews which also includes the author

/customers?filter[include][reviews]=author&filter[limit]=2

Return all customers including their reviews and orders

/customers?filter[include]=reviews&filter[include]=orders


Limit filter

A limit filter limits the number of records returned to the specified number (or less).
REST API

filter[limit]=_n_

You can also use stringified JSON format in a REST query.

Examples
Return only the first five query results:
REST

/cars?filter[limit]=5


Order filter

An order filter specifies how to sort the results: ascending (ASC) or descending (DESC) based on the specified property.
REST API
Order by one property:

filter[order]=propertyName <ASC|DESC>

Order by two or more properties:

filter[order][0]=propertyName <ASC|DESC>&filter[order][1][propertyName]=<ASC|DESC>...

You can also use stringified JSON format in a REST query.

Examples
Return the three loudest three weapons, sorted by the audibleRange property:
REST

/weapons?filter[order]=audibleRange%20DESC&filter[limit]=3


Skip filter

A skip filter omits the specified number of returned records. This is useful, for example, to paginate responses.
Use offset as an alias for skip.

REST API

?filter=[skip]=n

You can also use stringified JSON format in a REST query.

Examples
This REST request skips the first 50 records returned:

/cars?filter[skip]=50

Pagination Example
The following REST requests illustrate how to paginate a query result. Each request request returns ten records: the first returns the first ten, the second returns the 11th through the 20th, and so on…

/cars?filter[limit]=10&filter[skip]=0
/cars?filter[limit]=10&filter[skip]=10
/cars?filter[limit]=10&filter[skip]=20
...


Where filter

A where filter specifies a set of logical conditions to match, similar to a WHERE clause in a SQL query.

In the first form below, the condition is equivalence, that is, it tests whether property equals value. The second form below is for all other conditions.

filter[where][property]=value
filter[where][property][op]=value

For example, if there is a cars model with an odo property, the following query finds instances where the odo is greater than 5000:

/cars?filter[where][odo][gt]=5000

For example, here is a query to find cars with odo is less than 30,000:

/cars?filter[where][odo][lt]=30000

You can also use stringified JSON format in a REST query.

Important: There is a limit of twenty filters (combined with AND or OR) using this format, due to the use of qs. When there are more than twenty, the filter is converted into an Object where it is expecting an Array. See LoopBack issue #2824 for more details.


There are two ways to work around the filter limit:

  • Encode the large filter object as “stringified JSON.”
  • Override the limit manually in server/server.js, before boot is called.

Encode filter object as JSON

http://localhost:3000/api/Books
?filter={"where":{"or":[{"id":1},{"id":2},...,{"id":20"},{"id":21}]}}

Override limit in **server.js**

// In `server/server.js`, before boot is called
var loopback = require('loopback');
var boot = require('loopback-boot');
var qs = require('qs');

var app = module.exports = loopback();
app.set('query parser', function(value, option) {
  return qs.parse(value, {arrayLimit: 500});
});

app.start = function() {
  ...


Operators

This table describes the operators available in “where” filters. See Examples below.

Operator Description
= Equivalence. See examples below.
and Logical AND operator. See AND and OR operators and examples below.
or Logical OR operator. See AND and OR operators and examples below.
gt, gte Numerical greater than (>); greater than or equal (>=). Valid only for numerical and date values. See examples below.

For Geopoint values, the units are in miles by default. See Geopoint for more information.

lt, lte Numerical less than (<); less than or equal (<=). Valid only for numerical and date values.

For geolocation values, the units are in miles by default. See Geopoint for more information.

between True if the value is between the two specified values: greater than or equal to first value and less than or equal to second value. See examples below.

For geolocation values, the units are in miles by default. See Geopoint for more information.

inq, nin In / not in an array of values. See examples below.
near For geolocations, return the closest points, sorted in order of distance. Use with limit to return the n closest points. See examples below.
neq Not equal (!=)
like, nlike LIKE / NOT LIKE operators for use with regular expressions. The regular expression format depends on the backend data source. See examples below.
ilike, nilikeILIKE / NOT ILIKE operators for use with regular expressions. The regular expression format depends on the backend data source. See examples below.
regexp Regular expression. See examples below.

AND and OR operators
Use the AND and OR operators to create compound logical filters based on simple where filter conditions, using the following syntax.
REST

[where][<and|or>][0]condition1&[where][<and|or>]condition2...

Where condition1 and condition2 are a filter conditions.

Regular expressions
You can use regular expressions in a where filter, with the following syntax. You can use a regular expression in a where clause for updates and deletes, as well as queries.
Essentially, regexp is just like an operator in which you provide a regular expression value as the comparison value.

Tip: A regular expression value can also include one or more flags. For example, append /i to the regular expression to perform a case-insensitive match.

Where <expression> can be a:

  • String defining a regular expression (for example, '^foo' ).
  • Regular expression literal (for example, /^foo/ ).
  • Regular expression object (for example, new RegExp(/John/)).

Or, in a simpler format:

{where: {property: <expression>}}}

Where <expression> can be a:

  • Regular expression literal (for example, /^foo/ ).
  • Regular expression object (for example, new RegExp(/John/)).

For more information on JavaScript regular expressions, see Regular Expressions (Mozilla Developer Network).

REST

filter[where][property][regexp]=expression

Where:

A regular expression value can also include one or more flags. For example, append /i to the regular expression to perform a case-insensitive match.
Important: When using a regular expression flag with the REST API, you must precede the regular expression with a slash character (/).
The following REST query returns all cars for which the model starts with a capital “T”::

/api/cars?filter[where][model][regexp]=^T

The following REST query returns all models that start with either an uppercase “T” or lowercase “t”:

/api/cars?filter[where][model][regexp]=/^t/i

Note that since the regular expression includes a flag, it is preceded by a slash (/).

Examples

Equivalence
Weapons with name M1911:
REST

/weapons?filter[where][name]=M1911

Cars where carClass is “fullsize”:
REST

/api/cars?filter[where][carClass]=fullsize

Equivalently, in Node:

Cars.find({ where: {carClass:'fullsize'} });

gt and lt

For example, the following query returns all instances of the employee model using a where filter that specifies a date property after (greater than) the specified date:

/employees?filter[where][date][gt]=2014-04-01T18:30:00.000Z

The top three weapons with a range over 900 meters:

/weapons?filter[where][effectiveRange][gt]=900&filter[limit]=3

Weapons with audibleRange less than 10:

/weapons?filter[where][audibleRange][lt]=10

and / or
The following code is an example of using the “and” operator to find posts where the title is “My Post” and content is “Hello”.

Equivalent in REST:

?filter[where][and][0][title]=My%20Post&filter[where][and][1][content]=Hello

between
Example of between operator:

filter[where][price][between][0]=0&filter[where][price][between][1]=7

near
The where.<field>.near filter is different from other where filters: most where filters limitthe number of records returned, whereas near orders them, making it more like a SQL order by clause. By combining it with [limit](https://loopback.io/doc/en/lb2/Limit-filter.html), you can create a query to get, for example, the three records nearest to a given location.
For example:

/locations?filter[where][geo][near]=153.536,-28.1&filter[limit]=3

Inq
The inq operator checks whether the value of the specified property matches any of the values provided in an array. The general syntax is:

{where: { property: { inq: [val1, val2, ...]}}}

Where:

  • property is the name of a property (field) in the model being queried.
  • val1, val2, and so on, are literal values in an array.

Example of inq operator:
REST:

/medias?filter[where][keywords][inq]=foo&filter[where][keywords][inq]=bar

Or

?filter={"where": {"keywords": {"inq": ["foo", "bar"]}}}