PDA

View Full Version : How to query TreeStore



mnjacobs
7 Oct 2010, 12:52 PM
I am using a nested list and tree store and it works great. Now I need to have a way to query the tree store and it appears that TreeStore has no queryBy method.

Is there a way for me to query the contents of a TreeStore?

evant
7 Oct 2010, 2:53 PM
It's a bit more complicated because we can be dealing with remote asynchronous data. Can you give a bit more info about what you're trying to do?

mnjacobs
8 Oct 2010, 5:11 AM
I am using all static local data in the TreeStore. There is a large volume of nodes in the tree and I need to allow the user to search for records matching their search string. The search string would be used to find records where the search string is contained in any of several fields (probably through regex). After the above post, I discovered the TreeStore.getSubStore(node) method. It looks like this method returns a cached Store with the immediate children of the given node. I believe I need to start at the root node and recursively get the node substores and search each one (using one of the available Store methods) looking for matching records. The matching records will be displayed in a List. Selecting the item in the list will need to take the user to the detail card used by the nested list.

Is that the appropriate way to search the tree store? What other options do I have?

Thanks.

snapshotmedia
7 Dec 2010, 7:00 AM
mnjacobs: did you ever write this? If so do you fancy sharing your code? I've started writing it and coming up against a stumbling block accessing subStore items. Pretty sure I'll work it out but if you've already written this code then I'd appreciate having a look! :)

mnjacobs
7 Dec 2010, 8:49 AM
I did write this function, but am no longer using it. My search was really only against leaf nodes and I eventually separated the tree nodes from the leaf nodes so that they are in different stores. Here is the original recursive tree search I used. The specialized proxy in this example was to address otherwise poor start up times for the 17K tree nodes that were automatically loaded (and timing out on the iPad). The proxy implementation does not affect the search method used below.



Relevance = {};
Relevance.NOT_FOUND = 0;
Relevance.EXACT_PHRASE = 1;
Relevance.STARTS_WITH = 2;
Relevance.CONTAINS = 3;
Relevance.CONTAINS_ALL = 4;

var bookStore = new Ext.data.TreeStore({
model: 'ICD9Item',
autoLoad: true,
nodeParameter: 'codelevel',
proxy: {
type: 'book',
reader: {
type: 'tree',
root: 'items'
}
},
search: function(criteria) {
var fields = ['header', 'description', 'code'];
return this.searchByFields(criteria, fields, true);
},
searchByCode: function(criteria){
var fields = ['code'];
return this.searchByFields(criteria, fields, false);
},
searchByFields: function(criteria, fields, fuzzy) {
var rootNode = this.getRootNode();
var subStore = this.getSubStore(rootNode);
var results = new Array();
this.searchStore(this, subStore, criteria, fields, results, fuzzy);
return results;
},
/*
* Recursively search the tree by searching each
* flat substore at each node.
*/
searchStore: function(aStore, aSubstore, criteria, fields, results, fuzzy){
aSubstore.each(function(record){
if(results.length >= Ingenix.views.SearchView.Limit){
// Already exceeded the max so do not continue searching
return false;
}

var recordIsLeaf = false;
var leaf = record.get('leaf');
if(Ext.isDefined(leaf) && leaf == true){
recordIsLeaf = true;
}
// we should only search the leaf nodes
if(recordIsLeaf){
var relevance = this.relevance(record, criteria, fields, fuzzy);
if(relevance > 0){
var instance = Ext.ModelMgr.create({
relevance: relevance,
record: record,
}, 'SearchResults');
results[results.length] = instance;
}
}
else {
// need to recursively evaluate the children
var subSubstore = aStore.getSubStore(record);
this.searchStore(aStore, subSubstore, criteria, fields, results, fuzzy);
}

}, this);
},
relevance: function(record, criteria, fields, fuzzy){
/*
* Tests each record against the following criteria:
* Relevance Check (all case insensitive)
* 0. Not found
* 1. Exact phrase
* 2. Starts with criteria
* 3. Contains criteria
* 4. Contains all words in criteria
*/
var exactPhrase = new RegExp('\\b'+criteria+'\\b', '/i');
if(this.testPattern(exactPhrase, record, fields)){
return Relevance.EXACT_PHRASE;
}
if(fuzzy){
var exactPhraseStart = new RegExp('\\b'+criteria, '/i');
if(this.testPattern(exactPhraseStart, record, fields)){
return Relevance.STARTS_WITH;
}
var containsPhrase = new RegExp(criteria, '/i');
if(this.testPattern(containsPhrase, record, fields)){
return Relevance.CONTAINS;
}
var keyWords = criteria.split(" ");
var length = keyWords.length;
if(length > 1){
var allMatch = false;
for(i=0; i<length; i++){
var keywordPattern = new RegExp(keyWords[i], '/i');
if(this.testPattern(keywordPattern, record, fields)){
allMatch = true;
}
else {
allMatch = false;
break;
}
}
if(allMatch){
return Relevance.CONTAINS_ALL;
}
}
} // end if fuzzy
return Relevance.NOT_FOUND;
},
testPattern: function(pattern, record, fields){
// returns a boolean if the searched fields match the pattern

for(var index=0; index < fields.length; index++){
var match = pattern.test(record.get(fields[index]));
if(match){
return true;
}
}
}
});

anselmtmcclain
14 Feb 2011, 3:24 PM
I also wish TreeStore supported the findRecord / findBy methods of the vanilla Ext.Data.Store.

In my case, I also have a large number of static records parsed into a tree format and then loaded into the store. I'm using the store to back a NestedList, which is the only reason I'm using a TreeStore in the first place.

Thanks - ATM