Added support for AND style queries. Updated test page to incorporate
new query support. Added TODO list. Cleaned up a few functions and added some more clarifying comments.
This commit is contained in:
parent
662ff40fa2
commit
45508e74d6
16
TODO
Normal file
16
TODO
Normal file
@ -0,0 +1,16 @@
|
||||
Coming soon
|
||||
===========
|
||||
Better README
|
||||
Clearer function comments
|
||||
|
||||
|
||||
Maybe one day
|
||||
=============
|
||||
Larger/More extensive set of test data
|
||||
Wildcard support
|
||||
Stemming
|
||||
|
||||
|
||||
Probably not
|
||||
============
|
||||
Ranged queries
|
91
test.html
91
test.html
@ -7,10 +7,27 @@
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<input type="text" id="search" name="search" size="50" />
|
||||
<input type="button" id="btn_search" value="Search" />
|
||||
<br/><br/>
|
||||
<textarea name="output" id="output" rows="10" cols="40"></textarea>
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="or_search">Logical OR Search:</label></td>
|
||||
<td><input type="text" id="or_search" name="search" size="50" /></td>
|
||||
<td><input type="button" id="btn_or_search" value="Search"/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="and_search">Logical AND Search:</label></td>
|
||||
<td><input type="text" id="and_search" name="search" size="50" /></td>
|
||||
<td><input type="button" id="btn_and_search" value="Search" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td colspan="2">
|
||||
<textarea name="output" id="output" rows="10" cols="45"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -55,38 +72,52 @@
|
||||
output.val(output.val() + 'indexed in ' + (new Date().getTime() - s) + "ms\n");
|
||||
});
|
||||
|
||||
// Setup the search button
|
||||
$('#btn_search').click(function(){
|
||||
output.val(output.val() + 'Searching .. ');
|
||||
// Setup the search buttons
|
||||
$('#btn_or_search').click(function(){
|
||||
dosearch(false, $('#or_search').val());
|
||||
});
|
||||
|
||||
var s = new Date().getTime();
|
||||
var results = t.search($('#search').val());
|
||||
output.val(output.val() + 'completed in ' + (new Date().getTime() - s) + "ms\n");
|
||||
|
||||
var rtbl = $('#result_table').empty();
|
||||
for(var idx in results){
|
||||
var i = results[idx];
|
||||
|
||||
rtbl.append(
|
||||
'<tr>' +
|
||||
'<td>' + json[i]['id'] + '</td>' +
|
||||
'<td>' + json[i]['name'] + '</td>' +
|
||||
'<td>' + json[i]['email'] + '</td>' +
|
||||
'<td>' + json[i]['city'] + '</td>' +
|
||||
'<td>' + json[i]['state'] + '</td>' +
|
||||
'<td>' + json[i]['country'] + '</td>' +
|
||||
'<td>' + json[i]['rank'] + '</td>' +
|
||||
'<td>' + json[i]['desc'] + '</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
}
|
||||
$('#btn_and_search').click(function(){
|
||||
dosearch(true, $('#and_search').val());
|
||||
});
|
||||
|
||||
// Enter should work to search, too
|
||||
$('#search').keydown(function(e){
|
||||
if(e.which == 13){ $('#btn_search').click(); }
|
||||
$('#or_search').keydown(function(e){
|
||||
if(e.which == 13){ $('#btn_or_search').click(); }
|
||||
});
|
||||
|
||||
$('#and_search').keydown(function(e){
|
||||
if(e.which == 13){ $('#btn_and_search').click(); }
|
||||
}).focus();
|
||||
});
|
||||
|
||||
|
||||
function dosearch(and_search, value){
|
||||
var output = $('#output');
|
||||
output.val(output.val() + 'Searching .. ');
|
||||
|
||||
var s = new Date().getTime();
|
||||
var results = t.search(and_search, value);
|
||||
output.val(output.val() + 'completed in ' + (new Date().getTime() - s) + "ms\n");
|
||||
|
||||
var rtbl = $('#result_table').empty();
|
||||
for(var idx in results){
|
||||
var i = results[idx];
|
||||
|
||||
rtbl.append(
|
||||
'<tr>' +
|
||||
'<td>' + json[i]['id'] + '</td>' +
|
||||
'<td>' + json[i]['name'] + '</td>' +
|
||||
'<td>' + json[i]['email'] + '</td>' +
|
||||
'<td>' + json[i]['city'] + '</td>' +
|
||||
'<td>' + json[i]['state'] + '</td>' +
|
||||
'<td>' + json[i]['country'] + '</td>' +
|
||||
'<td>' + json[i]['rank'] + '</td>' +
|
||||
'<td>' + json[i]['desc'] + '</td>' +
|
||||
'</tr>'
|
||||
);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
49
tidx.js
49
tidx.js
@ -7,11 +7,11 @@ var Tidx = function()
|
||||
// regex used to find terms inside a value
|
||||
this.v_rx = new RegExp('(:?[a-z_-]+)|(\\d*\\.\\d+)|(\\d+)', 'mg');
|
||||
|
||||
// regex used to break out terms with a search
|
||||
// regex used to break out terms within a search
|
||||
this.s_rx = new RegExp('(:?([a-z\\d-_]+):){0,1}(:?(:?"(.+?)")|([a-z_-]+)|(\\d*\\.\\d+)|(\\d+))', 'img')
|
||||
|
||||
|
||||
// Adds data to index
|
||||
// Indexes data inside this object.
|
||||
this.index = function(tokenize, id, field, value)
|
||||
{
|
||||
var f;
|
||||
@ -64,7 +64,7 @@ var Tidx = function()
|
||||
|
||||
// Conducts a global search for a string (value) globally,
|
||||
// iterating through all fields.
|
||||
this.gsearch = function(result, value)
|
||||
this.gsearch = function(value, result)
|
||||
{
|
||||
// Refuse empty searches
|
||||
if(value.length === 0){ return []; }
|
||||
@ -75,10 +75,11 @@ var Tidx = function()
|
||||
for(var f in this._index){
|
||||
// Look for the specified search term
|
||||
if(this._index[f][v] !== undefined){
|
||||
// If it exists, add the result to r, adding in the weight
|
||||
// If it exists, add the result to r, adding in the weight and count
|
||||
for(var i in this._index[f][v]){
|
||||
if(result[i] === undefined){ result[i] = 0; }
|
||||
result[i] += this._index[f][v][i];
|
||||
if(result[i] === undefined){ result[i] = {'w': 0, 'c': 0}; }
|
||||
result[i]['w'] += this._index[f][v][i];
|
||||
result[i]['c']++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,7 +87,7 @@ var Tidx = function()
|
||||
|
||||
|
||||
// Conducts a field specific search for a string (value)
|
||||
this.fsearch = function(result, field, value)
|
||||
this.fsearch = function(field, value, result)
|
||||
{
|
||||
var f;
|
||||
switch(typeof field){
|
||||
@ -104,19 +105,22 @@ var Tidx = function()
|
||||
}
|
||||
|
||||
for(var i in this._index[f][v]){
|
||||
if(result[i] === undefined){ result[i] = 0; }
|
||||
result[i] += this._index[f][v][i];
|
||||
if(result[i] === undefined){ result[i] = {'w': 0, 'c': 0}; }
|
||||
result[i]['w'] += this._index[f][v][i];
|
||||
result[i]['c']++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Multi-term searching function - this is what you should use to
|
||||
// search with, returns an array of found ids ordered by weight
|
||||
this.search = function(search)
|
||||
// Multi-term searching function. This is what you should use
|
||||
// to search with. If and_query is true, returned results
|
||||
// must match every term. Otherwise, any ID matching any
|
||||
// term is returned.
|
||||
this.search = function(and_query, search)
|
||||
{
|
||||
var r = {};
|
||||
|
||||
var re;
|
||||
var re, tc=0;
|
||||
while((re = this.s_rx.exec(search)) !== null){
|
||||
var field = re[2];
|
||||
|
||||
@ -130,21 +134,30 @@ var Tidx = function()
|
||||
|
||||
// Global term
|
||||
if(field !== undefined && field.length !== 0){
|
||||
this.fsearch(r, field, value);
|
||||
this.fsearch(field, value, r);
|
||||
} else {
|
||||
this.gsearch(r, value);
|
||||
this.gsearch(value, r);
|
||||
}
|
||||
tc++;
|
||||
}
|
||||
|
||||
return this.sortresult(r);
|
||||
return this.order(r, (and_query ? tc : 0));
|
||||
};
|
||||
|
||||
|
||||
this.sortresult = function(o)
|
||||
// Orders the result of a query. Accepts an object as a result, and
|
||||
// the minimum floor count. In the event of an AND query, floor should
|
||||
// be quality to the number of search terms. Otherwise it should be zero.
|
||||
this.order = function(result, floor)
|
||||
{
|
||||
var t = [];
|
||||
|
||||
for(var i in o){ t.push([i, o[i]]); }
|
||||
for(var i in result){
|
||||
if(floor == 0 || result[i]['c'] >= floor){
|
||||
t.push([i, result[i]['w']]);
|
||||
}
|
||||
}
|
||||
|
||||
t.sort(function(a,b){ return b[1] - a[1]; });
|
||||
|
||||
var r = [];
|
||||
|
Reference in New Issue
Block a user