Archived
1
0

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:
Christopher Ramey 2012-04-03 02:44:32 +00:00 committed by cdramey
parent 662ff40fa2
commit 45508e74d6
3 changed files with 108 additions and 48 deletions

16
TODO Normal file
View 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

View File

@ -7,10 +7,27 @@
</style> </style>
</head> </head>
<body> <body>
<input type="text" id="search" name="search" size="50" /> <table>
<input type="button" id="btn_search" value="Search" /> <tr>
<br/><br/> <td><label for="or_search">Logical OR Search:</label></td>
<textarea name="output" id="output" rows="10" cols="40"></textarea> <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>&nbsp;</td>
<td colspan="2">
<textarea name="output" id="output" rows="10" cols="45"></textarea>
</td>
</tr>
</table>
<br/>
<table> <table>
<thead> <thead>
<tr> <tr>
@ -55,38 +72,52 @@
output.val(output.val() + 'indexed in ' + (new Date().getTime() - s) + "ms\n"); output.val(output.val() + 'indexed in ' + (new Date().getTime() - s) + "ms\n");
}); });
// Setup the search button // Setup the search buttons
$('#btn_search').click(function(){ $('#btn_or_search').click(function(){
output.val(output.val() + 'Searching .. '); dosearch(false, $('#or_search').val());
});
var s = new Date().getTime(); $('#btn_and_search').click(function(){
var results = t.search($('#search').val()); dosearch(true, $('#and_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>'
);
}
}); });
// Enter should work to search, too // Enter should work to search, too
$('#search').keydown(function(e){ $('#or_search').keydown(function(e){
if(e.which == 13){ $('#btn_search').click(); } if(e.which == 13){ $('#btn_or_search').click(); }
});
$('#and_search').keydown(function(e){
if(e.which == 13){ $('#btn_and_search').click(); }
}).focus(); }).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> </script>
</body> </body>
</html> </html>

49
tidx.js
View File

@ -7,11 +7,11 @@ var Tidx = function()
// regex used to find terms inside a value // regex used to find terms inside a value
this.v_rx = new RegExp('(:?[a-z_-]+)|(\\d*\\.\\d+)|(\\d+)', 'mg'); 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') 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) this.index = function(tokenize, id, field, value)
{ {
var f; var f;
@ -64,7 +64,7 @@ var Tidx = function()
// Conducts a global search for a string (value) globally, // Conducts a global search for a string (value) globally,
// iterating through all fields. // iterating through all fields.
this.gsearch = function(result, value) this.gsearch = function(value, result)
{ {
// Refuse empty searches // Refuse empty searches
if(value.length === 0){ return []; } if(value.length === 0){ return []; }
@ -75,10 +75,11 @@ var Tidx = function()
for(var f in this._index){ for(var f in this._index){
// Look for the specified search term // Look for the specified search term
if(this._index[f][v] !== undefined){ 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]){ for(var i in this._index[f][v]){
if(result[i] === undefined){ result[i] = 0; } if(result[i] === undefined){ result[i] = {'w': 0, 'c': 0}; }
result[i] += this._index[f][v][i]; 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) // Conducts a field specific search for a string (value)
this.fsearch = function(result, field, value) this.fsearch = function(field, value, result)
{ {
var f; var f;
switch(typeof field){ switch(typeof field){
@ -104,19 +105,22 @@ var Tidx = function()
} }
for(var i in this._index[f][v]){ for(var i in this._index[f][v]){
if(result[i] === undefined){ result[i] = 0; } if(result[i] === undefined){ result[i] = {'w': 0, 'c': 0}; }
result[i] += this._index[f][v][i]; result[i]['w'] += this._index[f][v][i];
result[i]['c']++;
} }
}; };
// Multi-term searching function - this is what you should use to // Multi-term searching function. This is what you should use
// search with, returns an array of found ids ordered by weight // to search with. If and_query is true, returned results
this.search = function(search) // must match every term. Otherwise, any ID matching any
// term is returned.
this.search = function(and_query, search)
{ {
var r = {}; var r = {};
var re; var re, tc=0;
while((re = this.s_rx.exec(search)) !== null){ while((re = this.s_rx.exec(search)) !== null){
var field = re[2]; var field = re[2];
@ -130,21 +134,30 @@ var Tidx = function()
// Global term // Global term
if(field !== undefined && field.length !== 0){ if(field !== undefined && field.length !== 0){
this.fsearch(r, field, value); this.fsearch(field, value, r);
} else { } 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 = []; 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]; }); t.sort(function(a,b){ return b[1] - a[1]; });
var r = []; var r = [];