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>
|
</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> </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
49
tidx.js
@ -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 = [];
|
||||||
|
Reference in New Issue
Block a user