Skip to content

Latest commit

 

History

History
182 lines (167 loc) · 4.99 KB

README.md

File metadata and controls

182 lines (167 loc) · 4.99 KB

advanced-search

Transform any search box / search term query into an advanced multi-field search with custom search operators (PHP, Node/XPCOM/JS, Python)

What it does

This enables out-of-the-box search boxes (actualy the search term query) to textualy encode complex (customizable) search queries, including AND/OR operators, greater-than, less-than, like, reference multiple different search fields and so on.. Similar to advanced search queries in search engines. Note, this does not include a GUI for that (although, one, can indeed use a GUI to build the complex search query), only the functionality to interpret the search term as complex query and get the parsed parts to be used then to do the actual query. The advantage is that one can use this to leverage ANY search form/search term to be able to encode a complex query without additional GUI or anything else extraneous and extravagant.

Example (see test/ folder)

var AdvancedSearch = require('../src/js/AdvancedSearch.js');

function echo( s )
{
    console.log( "object" === typeof s ? JSON.stringify(s, null, 4) : s );
}

echo("AdvancedSearch.VERSION = " + AdvancedSearch.VERSION);

echo(['term',AdvancedSearch().query('term')]);
echo(['~"term term2"',AdvancedSearch().query('~"term term2"')]);
echo(['field=term',AdvancedSearch().query('field=term')]);
echo(['field>=term field<=term2',AdvancedSearch().query('field>=term field<=term2')]);
echo(['field>=term field<=term2, field2~term3',AdvancedSearch().query('field>=term field<=term2, field2~term3')]);
echo(['field>="term term2" field<=term2, field2~"field2~term3", "field2~term3"',AdvancedSearch().query('field>="term term2" field<=term2, field2~"field2~term3", "field2~term3"')]);

output

AdvancedSearch.VERSION = 0.2.0
[
    "term",
    [
        [
            {
                "field": null,
                "op": null,
                "term": "term"
            }
        ]
    ]
]
[
    "~\"term term2\"",
    [
        [
            {
                "field": null,
                "op": "~",
                "term": "term term2"
            }
        ]
    ]
]
[
    "field=term",
    [
        [
            {
                "field": "field",
                "op": "=",
                "term": "term"
            }
        ]
    ]
]
[
    "field>=term field<=term2",
    [
        [
            {
                "field": "field",
                "op": ">=",
                "term": "term"
            },
            {
                "field": "field",
                "op": "<=",
                "term": "term2"
            }
        ]
    ]
]
[
    "field>=term field<=term2, field2~term3",
    [
        [
            {
                "field": "field",
                "op": ">=",
                "term": "term"
            },
            {
                "field": "field",
                "op": "<=",
                "term": "term2"
            }
        ],
        [
            {
                "field": "field2",
                "op": "~",
                "term": "term3"
            }
        ]
    ]
]
[
    "field>=\"term term2\" field<=term2, field2~\"field2~term3\", \"field2~term3\"",
    [
        [
            {
                "field": "field",
                "op": ">=",
                "term": "term term2"
            },
            {
                "field": "field",
                "op": "<=",
                "term": "term2"
            }
        ],
        [
            {
                "field": "field2",
                "op": "~",
                "term": "field2~term3"
            }
        ],
        [
            {
                "field": null,
                "op": null,
                "term": "field2~term3"
            }
        ]
    ]
]

The output consists of a tree representing the complex query, where the first level represents OR clauses and the second level AND clauses (inside each OR clause) including operators (default null interpret as you like) and specific search field references (see above example to get an idea).

One could then contruct an actual query out of this (note how the original GUI of the application did not change at all, it was simply leveraged in functionality) like the following:

var sql = "SELECT field1,field2,field3 FROM table";
var query = AdvancedSearch().query(GET['search']);
var OR = [];
for(var i=0; i<query.length; i++)
{
    var AND = [], factor = query[i];
    for(var j=0; j<factor.length; j++)
    {
        var term = factor[j];
        if ( null == term.field )
        {
            // default search field
            term.field = 'field1';
        }
        if ( null == term.op )
        {
            // default search operator
            term.op = '=';
        }
        if ( '~' == term.op )
        {
            term.op = 'LIKE';
        }
        AND.push(term.field+' '+term.op+' '+db.esc(term.term));
    }
    OR.push('(' + AND.join(') AND (') + ')');
}
sql += ' WHERE ' + OR.join(' OR ');
db.exec(sql, function(results){
    // get search results here
});