As you come to use data stores regularly within ExtJS applications, you’ll quickly come to realize just how powerful they are. With very little code, you can create robust data repositories that can not only store complex data, but can (perhaps more importantly) drive components within your applications.

At some point, however, you’ll need to retrieve data from your Store in a query-like manner. That is, instead of looking up a record by a known ID or position within the store, you may need to find one or more records based on a search term, a category, or whatever else is required by your app.

Of course, as with everything else, ExtJS makes this pretty simple. Let’s suppose that we have the following Model:

Ext.define("MyApp.model.Bookmark", {
     extend: "Ext.data.Model",
     idProperty: "id",
     fields: [
         {name: "id", type: "int"},
         {name: "target", type: "string"},
         {name: "title", type: "string"},
         {name: "category", type: "string"},
         {name: "created", type: "date"}
     ]
});

Nothing to crazy here. Just a simple model with some standard kinds of fields for storing data, in this case, “bookmarks.” Now, let’s define our data store:

Ext.define("MyApp.store.Bookmarks", {
    extend: "Ext.data.Store",
    model: "MyApp.model.Bookmark",
    autoLoad: true,
    storeId: 'bookmarks',
    proxy: {
        type: 'localstorage',
        id  : 'myapp-bookmarks'
    }
});

As with the model, this is very straightforward. We’ve configured a simple store which happens to have a localStorage proxy (change it if you want–ExtJS doesn’t care!).

Simple Data Lookup

Ok, so now that we’re up and running with our model and store, let’s pretend we’ve created a simple app to save bookmarks into our data store. As we’re plugging along, we find that we need to put some kind of tollgate in place to prevent the same bookmark from being entered over and over: after all, having one bookmark to Charlie the Unicorn 2 is certainly enough!

How can we prevent this? In our addBookmark() method, we can do a simple lookup on our data store to see if a bookmark with the same title already exists. This might look something like so:

function addBookmark(target,title,category) {
    var store = Ext.data.StoreManager.lookup('bookmarks');
    var match = store.find('title','title');
    if(match == -1) {
        ...add the bookmark
    }
}

In this simple example, we use the store’s find() method to search through the store’s records. The find() method takes two required arguments–the column to search, and the value to be used in the search–but has more flexibility for case-sensitivity, partial matches, etc. Based on whether the index of a record in our store is returned, we decide whether or not to add the new data to our store.

Of course, if we don’t care about the index of the record and simply want to get a matched record, we could use findRecord() instead. It functions in the same way, but returns a model instance instead of a record index.

More Complex Data Lookup

The store’s find() and findRecord() methods are great if you only need to find matches based on a single data column. What if you need to match on more than one column, though? For example, let’s say that we want to be able to store bookmarks with the same title as long as they belong to a different category. Obviously, our previous method will not work, since the method will prevent insertions of records with already-existent titles. Nope, we need something a bit more robust. Thankfully, ExtJS data stores have just the ticket: findBy().

The findBy() method’s power lies in the fact that you can specify a custom function that will be executed against every record in the data store. Within this custom function, you can do any manner of checks on the entire data record (not just the value of one column). If the conditions you specify succeed, the method will return the index of the first matching record.

So here’s what that might look like for our scenario of checking for the uniqueness of both bookmark title AND category:

function addBookmark(target,title,category) {
    var store = Ext.data.StoreManager.lookup('bookmarks');
    // custom function for finding record with complex criteria
    var match = store.findBy(function(record,id) {
        if(record.get('target')==target && record.get('category')==category) {
            return true;
        }
    });
    if(match == -1) {
        ...add the bookmark
    }
}

As you can see, the custom function is passed two arguments: the model instance of the currently-evaluated record, and the id of the record. Since we want to check to make sure that the combination of bookmark title and bookmark category are unique, we can simply check the “title” and “category” values of the would-be-bookmark against each model in our data store. If no match is found, we know the record is unique and we can add it to the data store. Magical :)

Wrapping Up

Obviously, the example provided above is very simple; however, I hope it shows just how easy it is to not only query data from a data store, but moreover to create custom functions to apply more complex query logic to the data in your stores.