Advanced Queries with BreezeJS

UPDATE: I recently published a WintellectNow course (Getting Started with Breeze.js) that goes into more depth using Breeze in the context of an AngularJS app.  Use code NSTIEGLITZ-13 for a free 2 week WintellectNow trial.

BreezeJS is a JavaScript library to help manage data in rich client web applications.  It’s especially useful in Enterprise and Line of Business (LOB) applications where users often query, save, and delete large amount of data.  Using the BreezeJS library is a joy to work with and feels like Entity Framework on the client.  BreezeJS provides:

  • Rich “LINQ like” Querying
  • Change Tracking
  • Entity Relationship Navigation
  • Client Caching
  • Validation
  • Offline Saving
  • Tight Integration with Web API and Entity Framework (neither are required)
  • Access to any RESTful API using custom metadata
  • Integration with JavaScript libraries/Frameworks like AnguarJS and KnockoutJS

 

In future posts I will expand on the entire feature set.  In this post, I’ll focus on the Rich “LINQ like” Querying.

LINQ like Querying

Advanced querying is probably the most compelling case for BreezeJS.  If you’re familiar with Entity Framework, querying in BreezeJS will feel quite intuitive.  With Breeze, you can easily write queries that filter, sort, page, project data, and even eager load relationships.

Filtering

Here is a simple query that filters a list of customers by Company Name:

var query = breeze.EntityQuery.from('Customers')
    .where('CompanyName', FilterQueryOp.Contain, 'Around');

The EntityQuery method creates a query which can be used against remote or local data stores.  The where clause applies the predicate as a filter (in this case – company name).  I’m using the FilterQueryOp “enum” (JavaScript doesn’t really have enums) which allows you to specify various predicates like Contains, Equals, LessThan, etc.  Check the full list here.

It is also possible to build up queries by chaining predicates.  This is useful, for example, if you have a search page with many optional search parameters.  In this example, I chain two predicates using and:

var query = breeze.EntityQuery.from('Customers');

var p1 = breeze.Predicate.create('ContactTitle', 'Contains', 'Rep');
var p2 = breeze.Predicate.create('City', 'Eq', 'London');
var pred = breeze.Predicate.and([p1, p2]);

query = query.where(pred);

I’ve used the predicate technique before with Entity Framework on the service tier; I’m glad to see a similar technique on the client.

Just to show you what’s possible, below is an example of a pretty advanced query.  It retrieves a list of all customers who have placed any orders with order details that have a quantity greater than 40:

var query = breeze.EntityQuery
     .from('Customers')
     .where('Orders', 'any', 'OrderDetails', 'all', 'Quantity', '>', 40);

As seem, it’s easy to filter deep into the object graph.

Now you have seen how to build a query, here is how you execute a query:

manager.executeQuery(query)
            .then(successCalllback)
            .fail(failCallback)
            .fin(finallyCallback); //execute the query and resolve to a promise

When you call executeQuery(query), Breeze will:

  1. Generate a URL which looks something like this:
    • http://localhost:50283/breeze/Customer/Customers?$filter=Orders/any(x1: x1/OrderDetails/all(x2: x2/Quantity gt 40)
    • Notice the where clause from the query has been converted into the URLs query string (a la ODATA).
  2. Asynchronously issues an HTTP GET to the server and expects a JSON payload in the returned HTTP response body
  3. Assuming the call was a success, Breeze reshapes the JSON data into Breeze entities and merges those entities into the local cache.  It then resolve the promise, allowing you, the developer, to handle the returned data via the successCallback.

 

Thanks Breeze – that was awesome!  Now in the successCallback I can bind the data to a view, log any errors in my failCallback, and do any cleanup in the fin callback.

Sorting

Sorting in BreezeJS is super straight forward and pretty powerful.  Check out this example from the BreezeJS documentation:

// Products sorted by their Category names, then by Product name (in descending order)
var query = breeze.EntityQuery.from('Products')
    .orderBy('Category.CategoryName, ProductName desc');

The code is pretty self explanatory.  It demonstrates that you can sort by related properties either ascending or descending.  As an alternative to adding the desc text, there is also an orderByDesc method.

// Products in descending name order (version 2)
var query = breeze.EntityQuery.from('Products')
    .orderByDesc('ProductName');

Paging

Breeze provides the ability to page data using the skip and take methods as demonstrated in this query:

// Get the 3rd page of 5 Customers
// by skipping 10 Customers and taking the next 5
var query = breeze.EntityQuery.from('Customers')
    .orderBy('ContactName')
    .skip(10)
    .take(5);

Projecting

If you don’t need all properties on an entity, you can use projection to retrieve only the relevant properties.  For example, this query would allow you to wire up a view which lists a customer’s contact name and company name:

//We only need the company name and contact name
var query = breeze.EntityQuery.from('Customers')
    .select('CompanyName, ContactName');

You can also project properties from related entities.  For example, this query retrieves a list of customers who placed orders with freight charges over $500:

var query = breeze.EntityQuery.from('Orders')
    .where('Freight', FilterQueryOp.GreaterThan, 500)
    .select('Customer.CompanyName');

Eager Loading

If you know you need related entities up front, it’s often a good idea to grab all of the data in a single call.  Maybe you need to build a view which displays a list of customers in Mexico and their related orders.  This query eagerly loads the customer’s orders:

var query = breeze.EntityQuery.from('Customers')
    .where('Country', 'eq', 'Mexico')
    .expand('Orders');

How easy is that?!

Conclusion

If you haven’t yet, go check out the BreezeJS documentation and download some of the samples.  Stay tuned for an upcoming BreezeJS video I’ll publish on WintellectNow.

Noel Stieglitz

View Comments

  • Is there a way to build a query to see if the property of a collection of objects is equal to the same property in an array/collection of said objects? Example: Employee.Customers, Customers has a property of Name. I have an array of Customers. Can I find all the Employees that have Customers with a Name that is contained in the array of Customers I've passed? It would be similar to this, but I can't figure out how to specify the array property to look at: predicate = new breeze.Predicate("customerList", "Any", "name", "==", this.customerArray.name());

  • Is there a way to build a query to see if the property on an object is equal to a similar property in an array/collection ofobjects? Example: I have a property on employee: Employee.Name. I have an array of Customer objects, Customer also has a name. Can I find all the Employees that have names in my Customers array? It would be similar to this, but I can't figure out how to specify the array property to look at: predicate = new breeze.Predicate("name", "==", this.customerArray.name()); customerArray is an observableArray, so I can't just add the property to the end of it.

Recent Posts

8-Step AWS to Microsoft Azure Migration Strategy

Microsoft Azure and Amazon Web Services (AWS) are two of the most popular cloud platforms.…

2 days ago

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

1 week ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

2 months ago