Write Better Queries with Breeze.js

Share this article

This article was peer reviewed by Agbonghama Collins. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Data volumes are growing rapidly and they are becoming more complex to maintain. Many developers want to avoid the problems and headaches that are caused by data issues during their job.

One of the libraries that makes our job easier is Breeze.js. In this article, we will talk about how we can write better queries with Breeze.js. But firstly, we should know what is Breeze.js and why it was created.

What Is Breeze.js?

Breeze.js is a JavaScript library that helps us manage data in rich client applications. Breeze runs natively in every browser and supports client-side querying, caching and dynamic object graphs.

The best thing about Breeze.js is that it doesn’t mirror the server-side model, but it creates it dynamically. With Breeze, the cached data is on the client side. It doesn’t need to query the server because it can query the cache instead. It saves the cache locally and offline. When it is reconnected, it syncs the changes.

Two of the strongest points of Breeze.js are rich queries and change tracking. Four powerful ways to query are filters, sorting, paging and projections. A query needs help to execute, that’s where Breeze EntityManager comes in. Each entity keeps track of its own changed state. We will discuss this later.

Breeze.js works well with a lot of frameworks including AngularJS, Backbone.js, Knockout, Node.js and many others.

Now let’s look at how to setup the environment and get to coding.

How to Install

Breeze can be downloaded from its repository on GitHub. The most common versions of Breeze are:

  • breeze.debug.js — This is the standard client library that I suggest using. It has support for third-party libraries including Backbone and Knockout.
  • breeze.min.js — Breeze.min.js is the minified breeze.debug.js, its size is 175 KB compared to size of breeze.debug.js, which is 602 KB.

There are two other ways to get Breeze: through Bower and npm. I prefer using Bower because I am more familiar with it. Open the terminal, then go to the client directory and run these two commands to get Breeze:

bower install breeze-client
bower install breeze-client-labs

In order to include Breeze into a the project, you should include this script tag inside the <body> of your page:

<script src="bower_components/breeze-client/build/breeze.debug.js"></script>

Older browsers that do not support ECMAScript 5 can cause problems for Breeze. A shim library is necessary to enable ES5 syntax on these browsers. For Internet Explorer users, it is recommended to enter this code inside the <head> tag, to avoid compatibility mode issues.

<meta http-equiv="X-UA-Compatible" content="IE=edge, chrome=1"/>

Breeze also needs some extensions to work normally:

  • a data service
  • a JavaScript component that performs AJAX requests
  • a model library for data binding (such as Knockout)
  • a promise library

So as to demonstrate Breeze in action, in the next section I’m going to show you how to get one of Breeze’s sample applications up and running. This will include all of these things out of the box.

Prerequisites for the Sample App

So as to run the sample app, you will need Node.js and MongoDB installed on your machine.

Node.js is free to use, and can be downloaded from the project’s homepage. If you have Bower or npm on your computer, you also have Node installed. If you are having trouble installing Node, then check out our tutorial on npm (which includes a section on this): A Beginner’s Guide to npm

MongoDB can be downloaded from their download page. They have guides on how to install for all major operating systems.

Setting up the Sample App

The first thing to do is grab a copy of the Breeze JavaScript Client sample applications. The easiest way to do this is using Git:

git clone https://github.com/Breeze/breeze.js.samples.git

Within the project, navigate to node/zza-node-mongo folder:

cd breeze.js.samples/node/zza-node-mongo

Here you see three folders: client, database, server. In the database folder unzip zza-mongo-database.zip.

cd database
unzip zza-mongo-database.zip

Now we need to find out the name of the directory MongoDB uses to read and write its data. By default this is /data/db on Linux and OS X and \data\db on Windows. However, if you installed MongoDB using a package manager, check the /etc/mongod.conf file provided by your packages to see the directory specified. For me (on Linux) it was /var/lib/mongodb.

Now move the files to that directory:

sudo mv zza.0 zza.1 zza.ns /var/lib/mongodb/

And change the ownership of the files to mongodb:nogroup:

sudo chown mongodb:nogroup /var/lib/mongodb/zza.*

If the mongodb server isn’t running, start it while pointing to this database directory:

sudo service mongod start

Back in the client folder /node/zza-node-mongo/client install Bower packages:

bower install

After the Bower components are installed, you need to navigate to the server folder /node/zza-node-mongo/server and install the Node modules:

npm install

Then, launch the app server from within the same folder:

node server.js

The final step is to open the browser and navigate to http://localhost:3000. If you see the figure below, you have followed all the right steps. If not, go back through the steps above to ensure you have done everything correctly, and consult this page for more information.

zza app welcome screen

Write Better Queries

Before we examine the CRUD app architecture, it’s good to learn about some of the Breeze components which helps us write better queries. The first thing to understand is the Breeze EntityManager. The EntityManager is the gateway to the persistence service and holds a cache of entities that the application is working with. These include entities that have been queried, added, updated, and marked for deletion.

var serviceName = 'breeze/todos';
var manager = new breeze.EntityManager(serviceName);

The serviceName serves to find the service end-point and the route to the Web API controller.

Filters

Writing queries with Breeze is very simple and straightforward. For example, look at this query which shows orders placed after February 1, 2010.

var query = EntityQuery.from('Orders')
    .where('OrderDate', '>', new Date(2010, 1, 1))

Another good way to write queries with Breeze is through compound conditions with predicates. The predicate is a condition that is true or false. Let’s combine two predicates with .and() (the AND operator) to create an expression that is true for both conditions.

In the sample below the first predicate selects all pizzas that cost more than 60 dollars. The second one selects all orders which were placed after January 15, 2015. When they are combined with .and() , they create a query which selects all pizzas that cost more than 60 dollars and were ordered after January 15, 2015.

var q1 = new Predicate('Pizza', '>;', 60);
var q2 = new Predicate('OrderDate', '>', new Date(2015, 0, 15));
var query = baseQuery.where(q1.and(q2));

Sorting

Another type of query is sorting. Breeze code for sorting products in descending name order is shown below. Its code is very readable.

var query = EntityQuery.from('Products')
    .orderBy('ProductName desc');

Breeze has three types of sorting. These are single property sort, multiple property sort, and related property sort.

Paging

Paging is the process of returning the results of a query in smaller subsets of data or, in other words, pages. Paging in Breeze can be done in two ways, with skip() and take().

In order to get the first five products which start with letter “E”, we could do the following:

var query = EntityQuery.from('Products')
    .where('ProductName', 'startsWith', 'E')
    .take(5)

Skip is used when you don’t want to take a specified number of objects, but rather returns the remainder of them. The code below skips the first five products and return the rest. It is necessary to use .orderBy() with .skip() because this is required by many server-side data services.

var query = EntityQuery.from('Products')
    .orderBy('ProductName')
    .skip(5);

Projections

Projection queries allow you to query for exactly those properties of an entity that you actually need. Let’s see an example showing a simple projection in Breeze which returns the names of customers beginning with the letter “C”.

var query = EntityQuery.from('Customers')
     .where('CompanyName', 'startsWith', 'C')
     .select('CompanyName');

There are four types of property projections: single data, single navigation, multiple property and related property projections.

If you want more information about Breeze queries you can consult their extensive documentation.

Simple App Architecture

Now let’s turn back to the app that we had up and running in the previous section (if all went well, it should still be available at http://localhost:3000).

Zza! is a CRUD app for ordering pizzas, salads, and drinks. It uses the BMEAN stack (which stands for Breeze + MEAN).

As we saw previously, the part of the app we are interested in (breeze.js.samples/node/zza-node-mongo) contains folders representing the client, server and database. The database folder contains the database (as the name implies). The server folder contains the relevant Node and Express files. Now let’s focus on the client side and see what’s in the client folder.

client folder structure

These are the most important components:

  • index.html — most of this file is occupied with CSS and JavaScript file loading.
  • app — this folder contains the AngularJS application module, its directives, services and views.
  • bower — inside this folder, you can find all of components which we installed on the client side through command-line.
  • css — here all of the app’s stylesheets are located.
  • images — the images and glyphicons for the app can be found in this folder.

Inside of index.html, which is the door to the application, many CSS and JavaScript files are loaded. In the body of index.html there is a bit of layout, but mostly <script> tags that lead to Angular components, application scripts, controllers and services.

<body class="ng-cloak" data-ng-app="app">

  <!--  Shell of the Sample App  -->
  <div data-ui-view="header"></div>

  <div id="shell-content" data-ui-view="content"></div>

  <div data-ui-view="footer"></div>

  <!--  Vendor Scripts  -->
  ...

  <!--  Application scripts  -->
  <script src="app/app.js"></script>  <!-- must load first -->
  <script src="app/appStart.js"></script>

  <!-- Feature Areas: controllers -->
  ...

  <!-- Directives & Routing -->
  ...

  <!-- Services -->
  <script src="app/services/config.js"></script>
  ...
</body>

AngularJS is the muscle of the application. It dynamically loads templated views, as well as the header and footer. You may notice three div tags, each with a data-ui-view attribute. It is here that the templated views are loaded. Most of the application activity happens inside the div tag with the id shell-content. This shows the orders page, the products page and most of what we see.

Breeze controls all the application’s data actions and movements. The Breeze EntityManager is focused on queries, caching, change-tracking, validating, and saving entity data. In this application, controllers make data requests through dataservice, which can be found at client/app/services/dataservice.

Conclusion

In this article we discussed Breeze.js, its features and some example queries to demonstrate how Breeze simplifies our job as developers. Hopefully you now have an idea of how to set up Breeze and understand the architecture of a sample app.

Breeze is a good tool to use because it decreases the amount of code we need to write, thus saving us time and making us more productive. If you guys are dealing with lots of data on your projects, I highly suggest learning Breeze. I’d love to hear your thoughts about Breeze.js in the comments below.

Frequently Asked Questions (FAQs) about Breeze.js

What Makes Breeze.js Different from Other JavaScript Libraries?

Breeze.js stands out from other JavaScript libraries due to its rich query capabilities. It allows developers to write complex queries in JavaScript that are then translated into a server-side query language. This feature makes it easier to fetch and manipulate data from a server. Additionally, Breeze.js supports tracking changes to data, which simplifies the process of saving changes back to the server.

How Can I Use Breeze.js for Data Management?

Breeze.js is a powerful tool for managing data in JavaScript applications. It provides a rich API for querying and saving data, as well as tracking changes to data. You can use Breeze.js to fetch data from a server, manipulate it in JavaScript, and then save the changes back to the server. This makes it a great choice for building data-intensive applications.

Can Breeze.js Work with Other JavaScript Frameworks?

Yes, Breeze.js is designed to work seamlessly with other JavaScript frameworks. It has built-in support for popular frameworks like Angular and Knockout, and it can be easily integrated with other frameworks as well. This flexibility makes Breeze.js a versatile tool for building JavaScript applications.

How Does Breeze.js Handle Server-Side Queries?

Breeze.js has a unique approach to handling server-side queries. It allows developers to write queries in JavaScript, which are then translated into a server-side query language. This means you can write complex queries without having to know the specifics of the server-side query language.

What Are the Benefits of Using Breeze.js for Data Manipulation?

Breeze.js offers several benefits for data manipulation. It provides a rich API for querying and saving data, making it easier to fetch and manipulate data from a server. Additionally, Breeze.js supports tracking changes to data, which simplifies the process of saving changes back to the server.

How Can I Integrate Breeze.js into My Existing JavaScript Application?

Integrating Breeze.js into an existing JavaScript application is straightforward. You can include the Breeze.js library in your application and start using its API to query and save data. Breeze.js also has built-in support for popular JavaScript frameworks, making it easy to integrate with these frameworks.

Can Breeze.js Handle Complex Queries?

Yes, one of the key features of Breeze.js is its ability to handle complex queries. It allows developers to write complex queries in JavaScript, which are then translated into a server-side query language. This makes it easier to fetch and manipulate data from a server.

How Does Breeze.js Support Data Change Tracking?

Breeze.js supports data change tracking by keeping track of changes to data as you manipulate it. This makes it easier to save changes back to the server, as Breeze.js knows exactly what changes have been made.

Is Breeze.js Suitable for Building Data-Intensive Applications?

Yes, Breeze.js is a great choice for building data-intensive applications. Its rich query capabilities and support for data change tracking make it easier to fetch, manipulate, and save data, which are key tasks in data-intensive applications.

How Can I Get Started with Breeze.js?

Getting started with Breeze.js is easy. You can download the Breeze.js library from the official website and include it in your JavaScript application. From there, you can start using the Breeze.js API to query and save data. There are also plenty of resources and tutorials available online to help you get started.

Taulant SpahiuTaulant Spahiu
View Author

Taulant is a web developer who is passionate about JavaScript and its technologies. He holds a bachelor's degree in Computer Engineering and is proficient in JavaScript, Java and AngularJS. In his free time, he loves playing with new web technologies.

breeze.jscrud appEntityManagerjameshmongodbnode.jsoffline apprich data
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week