0

I'm writing up a search engine with JS and jQuery rather than resulting to my PHP database but i'm having an issue understanding how I will construct the 'query'.

Currently, the following steps are taken to fill the array of objects.

1) PHP backend develops a JSON file with all holidays in a specific database.

2) The Javascript frontend pulls this JSON and adds all of it to an array through a loop.

3) The user has a few boxes where they can search the array with and all the results are added to a 'results' array which is updated accordingly each time.

One issue i'm having is; how do I deal with multiple if clauses? For example, if both search_time and search_state != "all", I would need to narrow the search down to only include objects where search_time AND search_state values are met. Currently the query is an OR query.

I come from a background of SQL so approaching Javascript like search is a bit different for me, any help would be appreciated.

Javascript search below:

 for (var i=0; (i <= holidays.length) && (found < limit); i++) {
    var h = holidays[i];
    console.log(h);
    complete = false;
    while (!complete && (h != undefined)) {
        if (search_terms != "" && search_terms != undefined) {
            if (like(h.title, search_terms) || like(h.state, search_terms) || like(h.country, search_terms) || like(h.location, search_terms)) {
                results[found] = h;
                found += 1;
                complete = true;
            }
        }
        if (search_country != "all") {
            if (h.country != undefined) {
                if (like(h.country, "Australia") && !complete) {
                    results[found] = h;
                    found += 1;
                    complete = true;
                }
            }
        }
        if (search_state != "ALL") {
            if (like(h.state, search_state) && !complete) {
                results[found] = h;
                found += 1;
                complete = true;
            }
        }
        if (search_time != "all") {
            var cyear = new Date().getFullYear();
            var nyear = cyear + 1;
            if (search_time == 'n-year' && !complete) {
                if (h.startsyd != undefined) {
                    if (new Date(h.startsyd).getFullYear() >= nyear) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
                else if (h.melbstart != undefined) {
                    if (new Date(h.melbstart).getFullYear() >= nyear) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
            }
            else if (search_time == 'c-year' && !complete) {
                if (h.startsyd != undefined) {
                    if (new Date(h.startsyd).getFullYear() >= cyear && new Date(h.startsyd).getFullYear() < nyear) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
                else if (h.melbstart != undefined) {
                    if (new Date(h.melbstart).getFullYear() >= cyear && new Date(h.melbend).getFullYear() < nyear) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
            }
            else if (search_time == '6-months' && !complete) {
                var six = new Date().setMonth(this.getMonth() + 6);
                if (h.startsyd != undefined) {
                    if (new Date(h.startsyd <= six)) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
                else if (h.melbstart != undefined) {
                    if (new Date(h.melbstart <= six)) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
            }
            else if (search_time == '3-months' && !complete) {
                var three = new Date().setMonth(this.getMonth() + 3);
                if (h.startsyd != undefined) {
                    if (new Date(h.startsyd <= three)) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
                else if (h.melbstart != undefined) {
                    if (new Date(h.melbstart <= three)) {
                        results[found] = h;
                        found += 1;
                        complete = true;
                    }
                }
            }
        }
        complete = true;
    }
}
Oliver Kucharzewski
  • 2,523
  • 4
  • 27
  • 51

1 Answers1

0

this way will allows you to:

1) add more field comparisons (read about items marked with number 4.a and 4.b, you can add 4.c, 4.d etc.., trying to keep things clear).

2) allows you to select in AND or OR modes (with sensitivity)

3) Save you a lot of time and code by using jQuery.

4) a strstr function is provided, read the scripts sections for comments. The original function (link) returns a string, i make a modification to it by returning a null instead of a "No match" string.

// 1. lets setup a database, you can pull it from PHP or some other else..
//
var holidays = [
   { title : "aaskjqkwqiuwqi" , state : "florida" },
  { title : "aaaaksjak222jski" , state : "california" },
  { title : "1281827888282" , state : "california" },
  { title : "aksjakjkas88112" , state : "florida" }
];

// 2. lets define some inputs
//
var i_find = "88";   // what to find
var i_state = "all";  // what to find

// 3. define some internal conditions.
//
var result_type = 'AND';  // set to: AND or OR
var at_least = 2; // when OR, at least N items to have a match..
var results = [];

// 4. for each holiday entries we will count how many conditions match,
//  and depending on the search modality (AND or OR) then we put results
//
$(holidays).each(function(index,obj){
    var matches = [];

    // 4.a find by title and say if it success or not
    matches.push({ res: strstr(obj.title, i_find) ? true : false });
    
    // 4.b find by state, and again, say if it success or not
    if("all" != i_state)
    matches.push({ res: strstr(obj.state, i_state) ? true : false });

    // 4.c more search attributes ? add them here
     

    // 5. process results
    // we will count how many questions (4a,4b..) success:
    var n_matches = 0;
    $(matches).each(function(i,o){ if(true == o.res) n_matches++; });

    // 5.b return results depending on the search model: AND or OR, 
    // 
    if(('AND' == result_type) && (n_matches == matches.length))
       results.push(obj);  
    if(('OR' == result_type) && (n_matches > at_least))
       results.push(obj);  
});

// 6. we have results, if 'results' has entries.
console.log('Search Type: '+result_type);
results.length ? console.log('WE HAVE A MATCH FOR:'
  +i_find+' please examine results array') 
     : console.log('NO MATCH');

if(results.length) console.log(results);
// 7. have a nice day. :)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script>
  /* taken from: https://stackoverflow.com/a/9123997/937815 */
  function strstr (haystack, needle) {
    var i = 0,
        tempLength = 0,
        temp = [];
    for (;;) {
        if (haystack[i] === undefined || needle == null) {
            return null;
        }
        //if the char doesn't match then reset
        else if (haystack[i] !== needle[tempLength]) {
            temp = [];
            tempLength = 0;
        } 
        //the char matches so let's store it.
        else if (haystack[i] === needle[tempLength]) {
            temp[tempLength] = haystack[i];
            if (needle[tempLength + 1] === undefined) {
                return temp;
            }
            tempLength++;
        }
     i++;
   }
};
</script>
Community
  • 1
  • 1
christian
  • 538
  • 5
  • 8