PDA

View Full Version : [FIXED-697] Store's query() and filter() functions only check beginning of values



cornyflake
13 Dec 2008, 5:12 AM
The Store's query() and filter() functions will return records with field values that only start with the query value.

Example:


var people = new Ext.data.SimpleStore({
data: [
[1, 5],
[2, 55]
],
id: 0,
fields: ['id', 'group_id']
});

// shows me people in group 55 as well
people.filter('group_id', 5);


I know there's a lot of code depending on this, but this has surpised me and probably created a lot of unknown bugs in applications that need exact matching (ex. foreign field ids). Perhaps the API documentation should note this behavior in the actual description and Ext should provide functions that search exact matches (I can't post in the "Feature Requests" forum).

Here's what I use. Probably crappy code, but it works within the Store's system:


queryExact: function(property, value){
return this.query(property, new RegExp('^' + Ext.escapeRe(String(value)) + '$'));
},
filterExact: function(property, value){
return this.filter(property, new RegExp('^' + Ext.escapeRe(String(value)) + '$'));
}


Thanks!

Blake

brookd
13 Dec 2008, 3:13 PM
That is weird. I checked, and your right, it does return 55. That doesn't seem logical, I know i have code that is filter by and id value and I didn't expect it to return results like this. I would think this is a bug??

mjlecomte
13 Dec 2008, 8:05 PM
I'm not saying your code is wrong, but your code looks the same as the original?



filter : function(property, value, anyMatch, caseSensitive){
if(Ext.isEmpty(value, false)){
return this.clone();
}
value = this.createValueMatcher(value, anyMatch, caseSensitive);
return this.filterBy(function(o){
return o && value.test(o[property]);
});
},

// private
createValueMatcher : function(value, anyMatch, caseSensitive){
if(!value.exec){ // not a regex
value = String(value);
value = new RegExp((anyMatch === true ? '' : '^') + Ext.escapeRe(value), caseSensitive ? '' : 'i');
}
return value;
},

cornyflake
14 Dec 2008, 2:19 AM
MJ, here's the difference:


queryExact: function(property, value){
return this.query(property, new RegExp('^' + Ext.escapeRe(String(value)) + '$'));
},
filterExact: function(property, value){
return this.filter(property, new RegExp('^' + Ext.escapeRe(String(value)) + '$'));
}


It'd be more efficient to use a string than a regexp, but this way it's more modular.

mjlecomte
14 Dec 2008, 5:01 AM
Thank you subsidiary of Kellogg's. :) My regExp knowledge is abysmal.

Seems like it would be better to add an exactMatch parameter:



filter : function(property, value, anyMatch, caseSensitive, exactMatch){
if(Ext.isEmpty(value, false)){
return this.clone();
}
value = this.createValueMatcher(value, anyMatch, caseSensitive, exactMatch);
return this.filterBy(function(o){
return o && value.test(o[property]);
});
},

// private
createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch){
if(!value.exec){ // not a regex
value = String(value);
value = new RegExp(
(anyMatch === true ? '' : '^') +
Ext.escapeRe(value) +
(exactMatch === true ? '$' : '') ,
caseSensitive ? '' : 'i'
);
}
return value;
},


I suppose someone will probably say that if you want such screening you should specify your own regular expression as the second argument to filter() though.

You may want to post this in the documention bugs thread. Some verbage could be added to caution the developer, and even add a code snippet how to implement this expression which might be a common use case.

enjoyfrancis
22 Aug 2009, 3:29 PM
Hi, where should I put this code?
on the listener?

Artistan
12 Oct 2009, 12:36 PM
I am simply using this in an overrides.js that I include after ext.



// this to allow for an exact match query/filter
Ext.override(Ext.data.Store, {
queryExact: function(property, value){
return this.query(property, new RegExp('^' + Ext.escapeRe(String(value)) + '$'));
},
filterExact: function(property, value){
return this.filter(property, new RegExp('^' + Ext.escapeRe(String(value)) + '$'));
}
});


then you can do this...



var people = new Ext.data.SimpleStore({
data: [
[1, 5],
[2, 55]
],
id: 0,
fields: ['id', 'group_id']
});

// shows me JUST people in group 5
people.filterExact('group_id', 5);

jheid
25 Oct 2009, 8:40 AM
When will this be fixed (not fixed in 3.0.3)???

What do you expect when invoking store.find ('id', 1)? I'll get id:16 - even no comment in the doc!

efreitasrj
30 Nov 2009, 10:06 AM
BUMP !

I just ran into the same problem and it took me some time to figure it out... Adding a comment to the documentation in bold red letters saying something like: "When searching for numeric id values, use RegExp for an exact match" would be a time saver...

Jamie Avins
30 Nov 2009, 12:35 PM
It's already in for 3.1. In order to maintain compatibility, we are indeed adding an extra parameter to the function as MJ suggests.

liquidl
5 Feb 2010, 5:29 AM
Hi! If you are putting in these changes in 3.1 also fix the ComboBox because it's store is filtering data without exact match! :-?

mystix
5 Feb 2010, 8:24 AM
Hi! If you are putting in these changes in 3.1 also fix the ComboBox because it's store is filtering data without exact match! :-?

a combo uses a store. if the store's fixed, so will the combo.

or am i missing something?

liquidl
6 Feb 2010, 6:48 AM
No, you are correct. But what I was trying to suggest is that the code of ComboBox should specify by default (maybe make it a config opion) that it's store has to return only exact match of the query, just as someone above said this would prevent from problems with external keys...I think that it is the most natural way for a Combo to use it's valueField as id field and it's got to be unique...

liquidl
6 Feb 2010, 8:27 AM
i ment query by valueField value should return unique record

moegal
8 Mar 2010, 1:32 PM
has query and filter been updated to handle exactMatch?

I do not see it in the documantation.

Thanks, Marty

Jamie Avins
9 Mar 2010, 9:22 AM
It's in mixedCollection, but I'm not sure why Store isn't using the parameter at the moment. I'll check into it and make sure it's there for 3.2.

moegal
9 Mar 2010, 10:16 AM
thanks!

Jamie Avins
9 Mar 2010, 10:41 AM
[type]: fix
[module]: Store
[id]: #697
[desc]: Store filters updated to support an exactMatch flag. Additional unit tests for anyMatch, caseSensitive, and exactMatch flags. Documentation updated as well.