• If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

DataStore-Your First Find

Page history last edited by geoffreyd 13 years, 6 months ago

The DataStore framework makes it easy to find groups of records based on search criteria, both locally in-memory and on your server.  For searches that rely only on data you have loaded into memory, the framework can even automatically update your results with “live record arrays”; much like “smart groups” in a desktop application.

 

Finding All Records

 

You might remember from the previous section that retrieving an individual record in the store involves using the find() method with a record type and id:

 

var contact = MyApp.store.find(MyApp.Contact, 1);

 

Finding all of the records with a particular type in your application is just as easy; just leave out the id:

 

var contacts = MyApp.store.find(MyApp.Contact);

 

When you call find() in this way, the store will do two things:

 

  1. Notify your data source, asking it to load any contacts into memory.  Your data source can handle this in any way that makes sense; including doing nothing.
  2. Immediately return a record array that will contain all of the contact records as they are loaded into memory.

 

Record Arrays

 

Record arrays are special objects (instances of SC.RecordArray) that implement the SC.Enumerable and SC.Array mixins.  This means that you can access items in a record array, and iterate over them, just like you would could a regular native Array.   For example, to get the size of a record array, you just get the length property:

 

contacts.get(‘length’)

>>> 5

 

Likewise, you can retrieve a record at any index using SC.Array.objectAt():

 

contacts.objectAt(3);

>> MyApp.Contact({ firstName: “John”, lastName: “Doe”, guid: 1 }, READY_CLEAN)

 

You can even use iterators to work on each item in the array:

 

contacts.forEach(function(contact) {

  console.log(contact.get(‘firstName’));

}, this);

 

>> “Michael”

>> “Jane”

>> “John”

>> “Jan”

>> “Jana”

 

contacts.getEach(“firstName”)

>> [“Michael”, “Jane”, “John”, “Jan”, “Jana”]

 

IMPORTANT: Remember that SC.Enumerable and SC.Array are mixins that are added to the native JavaScript Array object.  You cannot simply access records in a record array using the brackets ([]) like you can with a native Array.  Always use objectAt() and related methods defined on these mixins instead.

 

Record arrays are usually immutable (i.e. read-only), though in some advanced cases that can be mutable (i.e. you can add/remove records).  When finding records in this way, however, they will always be immutable.

 

Record arrays differ from native arrays in that they will defer actually creating Record instances for your data until you actually ask for them.  This means you can use find() to search for very large data sets without paying a huge performance penalty since the record arrays themselves only do the minimal work possible.

 

Updating Your Results

 

When you find all records in this way, the returned record array is “live”.  This means that it will update automatically as the state of your in-memory store changes.  If you create a new Contact in memory, it will appear immediately in this record array.  If you delete a contact, it will be removed.  Likewise if your data source loads new contacts into memory, they will immediately appear as well.

 

Using flush()

 

To maximize performance, live record arrays will typically only update at the end of the run loop; after the rest of your code executes.  This means, for example, that if you create a new record and then immediately inspect a related live record array, the new record may not yet appear in the array until after your code is finished running.  See the example below:

 

// find all contacts in memory

var contacts = MyApp.store.find(MyApp.Contact);

 

// create a new contact in the store

var newContact = MyApp.store.create(MyApp.Contact, 1);

 

// will not appear yet because it is same run loop

contacts.indexOf(newContact)  

>>> -1

 

----- NEXT RUN LOOP

 

// run loop has finished - contacts have now updated

contacts.indexOf(newContact);

>>> 1 

 

By deferring updates in this way, record arrays can avoid expensive computations and sending out notifications until you are finished making any changes you might want to make to your records.  This can dramatically improve performance. 

 

Normally, deferred updates in record arrays will not directly impact your code.  If you are using a record array as content for a controller or as a part of a binding, changes will propagate at the right time anyway so your UI will never appear out of sync.  If you ever do need to force a record array to update immediately, however, you can do so by calling flush().  

 

SC.RecordArray#flush() will immediately update the record array with any pending changes, notifying any observers in the process.  If no changes are pending, flush() has no effect.  Calling flush() can be very expensive so it is usually best to design your app to avoid it; but it can be useful if you need to get around the deferred updating behavior of live record array.  

 

// find all contacts in memory

var contacts = MyApp.store.find(MyApp.Contact);

 

// create a new contact in the store

var newContact = MyApp.store.create(MyApp.Contact, 1);

 

// will not appear yet because it is same run loop

contacts.indexOf(newContact)  

>>> -1

 

// flush pending changes immediately.  don’t wait for runloop

contacts.flush();

contacts.indexOf(newContact);

>>> 1

 

Using refresh()

 

Sometimes you may want to force a record array to simply reload its results. This is especially important when working with record arrays that are not live updating, such as those that depend on loading data from the server (covered in a later section).

 

To force a record array to reload its results just called refresh() on the record array instead.  Note the difference here from flush().  SC.RecordArray#flush() will apply any pending changes to a live record array immediately.  SC.RecordArray#refresh() will actually rebuild the search from scratch.

 

Moving On

 

Get more advanced Finding With Queries » 

or back to DataStore Programming Guide Home »

Comments (0)

You don't have permission to comment on this page.