Follow us on Twitter X-Cart on Facebook Wiki
Shopping cart software Solutions for online shops and malls

Improved Search Function

 
Reply
   X-Cart forums > X-Cart 4 > Dev Questions
 
Thread Tools Search this Thread
  #151  
Old 09-29-2005, 01:42 PM
 
Don L Don L is offline
 

Member
  
Join Date: Sep 2005
Posts: 27
 

Default

leighj:

Interesting approach, but it isn't quite working for me. I've only been using x-cart for a week, so forgive me if I'm missing something obvious here.

It seems like the code that actually computes $searchscore is missing.
__________________
GetItCheap.com
x-cart v4.0.17

TheNewDonald.com - Internet Marketing Blog
Reply With Quote
  #152  
Old 09-29-2005, 02:28 PM
 
leighj leighj is offline
 

Member
  
Join Date: Feb 2005
Posts: 15
 

Default

Don't worry I've been banging my head on X-Cart for 7 months now

Check the additional Additional Fields String section code
yes I did forget a line or two WHOOPS ...
Code:
$add_fields[]=$scorestr . " 0 as searchscore";
Which goes at the end of the Additional Fields String section code (I fixed my original post also)

Searchscore is calculated in MySQL not in PHP.
This is where the score is found
Code:
# # Generate additional fields string # $add_fields_string = ''; $scorestr=""; // Add score to fields - LNJ if (!empty($data["by_title"]) && count($search_words)>0) { $scorestr.="if($sql_tbl[products].product like '%". $data["substring"] ."%',5,0) + "; //Add high score for exact match - LNJ $topscore=4; // Yeah I know HARDCODED - LNJ $scoredesc=$topscore/count($search_words); //Get decrementing number for scores - LNJ foreach($search_words as $search_word){ $scorestr.="if($sql_tbl[products].product like '%". $search_word ."%',$topscore,0) + "; //add individual word score - LNJ $topscore=$topscore-$scoredesc; //Descrement individual score for word - LNJ } }
SNIP CODE FOR Short and Long Description
Code:
$add_fields[]=$scorestr . " 0 as searchscore";
The create an additional SINGLE field that consists of several if statements that follow this logic (for a 5 word search)
  1. If the phrase matches add 5 to the score
  2. If the first word is found matches add 4 to the score
  3. If the second word is found add 4-(4/Number of search words) to the score
  4. If the third word is found add 4-(2*(4/Number of search words)) to the score
  5. If the fourth word is found add 4-(3*(4/Number of search words)) to the score
  6. If the fifth word is found add 4-(4*(4/Number of search words)) to the score

This lets the database do the filter for the records and then sort and limit the data sent back to PHP. So PHP has only 10 records in the result set an not 1000 or so to calculate and sort.

Granted this approach does increase the load on the database engine and is contained in a sql statement but it provides the following benefits over having PHP do the calculation
  • Reduces the database connection load (only returns 10 rows instead of 1000)
  • Sorting is a (hopefully optimized) database function rather than several PHP functions
  • Less code (sorting this result in PHP would be cumbersome at best)

I hope this helps...
__________________
  • X-Cart Version 4.1
  • PHP Version 4.4.x eAccelerator
  • MySQL 4.1
  • Fedora Core 1
  • Dual Xeon 2.4Ghz Hyperthreading enabled 2GB Ram
Reply With Quote
  #153  
Old 09-29-2005, 02:34 PM
 
leighj leighj is offline
 

Member
  
Join Date: Feb 2005
Posts: 15
 

Default Full source

For those who've asked... all of it
WARNING If you mess up your X-cart don't cry to me... this was applied to a 4.0.16 search.php

Code:
<?php /*****************************************************************************\ +-----------------------------------------------------------------------------+ | X-Cart | | Copyright (c) 2001-2005 Ruslan R. Fazliev <rrf@rrf.ru> | | All rights reserved. | +-----------------------------------------------------------------------------+ | PLEASE READ THE FULL TEXT OF SOFTWARE LICENSE AGREEMENT IN THE "COPYRIGHT" | | FILE PROVIDED WITH THIS DISTRIBUTION. THE AGREEMENT TEXT IS ALSO AVAILABLE | | AT THE FOLLOWING URL: http://www.x-cart.com/license.php | | | | THIS AGREEMENT EXPRESSES THE TERMS AND CONDITIONS ON WHICH YOU MAY USE | | THIS SOFTWARE PROGRAM AND ASSOCIATED DOCUMENTATION THAT RUSLAN R. | | FAZLIEV (hereinafter referred to as "THE AUTHOR") IS FURNISHING OR MAKING | | AVAILABLE TO YOU WITH THIS AGREEMENT (COLLECTIVELY, THE "SOFTWARE"). | | PLEASE REVIEW THE TERMS AND CONDITIONS OF THIS LICENSE AGREEMENT | | CAREFULLY BEFORE INSTALLING OR USING THE SOFTWARE. BY INSTALLING, | | COPYING OR OTHERWISE USING THE SOFTWARE, YOU AND YOUR COMPANY | | (COLLECTIVELY, "YOU") ARE ACCEPTING AND AGREEING TO THE TERMS OF THIS | | LICENSE AGREEMENT. IF YOU ARE NOT WILLING TO BE BOUND BY THIS | | AGREEMENT, DO NOT INSTALL OR USE THE SOFTWARE. VARIOUS COPYRIGHTS AND | | OTHER INTELLECTUAL PROPERTY RIGHTS PROTECT THE SOFTWARE. THIS | | AGREEMENT IS A LICENSE AGREEMENT THAT GIVES YOU LIMITED RIGHTS TO USE | | THE SOFTWARE AND NOT AN AGREEMENT FOR SALE OR FOR TRANSFER OF TITLE.| | THE AUTHOR RETAINS ALL RIGHTS NOT EXPRESSLY GRANTED BY THIS AGREEMENT. | | | | The Initial Developer of the Original Code is Ruslan R. Fazliev | | Portions created by Ruslan R. Fazliev are Copyright (C) 2001-2005 | | Ruslan R. Fazliev. All Rights Reserved. | +-----------------------------------------------------------------------------+ \*****************************************************************************/ # # $Id: search.php,v 1.38.2.61 2005/09/19 06:45:33 max Exp $ # if ( !defined('XCART_SESSION_START') ) { header("Location: ../"); die("Access denied"); } $advanced_options = array("productcode", "productid", "provider", "price_max", "avail_max", "weight_max", "forsale", "flag_free_ship", "flag_ship_freight", "flag_global_disc", "flag_free_tax", "flag_min_amount", "flag_low_avail_limit", "flag_list_price", "flag_vat", "flag_gstpst", "manufacturers"); $sort_fields = array( "productcode" => func_get_langvar_by_name("lbl_sku"), "title" => func_get_langvar_by_name("lbl_product"), "price" => func_get_langvar_by_name("lbl_price"), "orderby" => func_get_langvar_by_name("lbl_default") ); if($current_area == 'A' || $current_area == 'P') $sort_fields["quantity"] = func_get_langvar_by_name("lbl_quantity"); if (empty($search_data)) { $search_data = array(); } if ($REQUEST_METHOD == "POST" && $mode == 'search') { # # Update the session $search_data variable from $posted_data # if (!empty($posted_data)) { $need_advanced_options = false; foreach ($posted_data as $k=>$v) { if (!is_array($v) && !is_numeric($v)) $posted_data[$k] = stripslashes($v); if (in_array($k, $advanced_options) and $v !== "") $need_advanced_options = true; } if (!$need_advanced_options) $need_advanced_options = (doubleval($posted_data["price_min"]) != 0 || intval($posted_data["avail_min"]) != 0 || doubleval($posted_data["weight_min"]) != 0); if (!$need_advanced_options and $current_area == "C" and !empty($posted_data["categoryid"])) $need_advanced_options = true; $posted_data["need_advanced_options"] = $need_advanced_options; # # Data convertation for Feature comparison module # if(!empty($active_modules['Feature_Comparison'])) { include $xcart_dir."/modules/Feature_Comparison/search_define.php"; } if (empty($search_data["products"]["sort_field"])) { $posted_data["sort_field"] = "title"; $posted_data["sort_direction"] = 0; } else { $posted_data["sort_field"] = $search_data["products"]["sort_field"]; $posted_data["sort_direction"] = $search_data["products"]["sort_direction"]; } $search_data["products"] = $posted_data; $search_data["is_modify"] = $is_modify; } func_header_location("search.php?mode=search"); } if ($mode == "search") { # # Perform search and display results # $data = array(); $flag_save = false; # # Prepare the search data # if (!empty($sort) and isset($sort_fields[$sort])) { # Store the sorting type in the session $search_data["products"]["sort_field"] = $sort; $flag_save = true; } if (isset($sort_direction)) { # Store the sorting direction in the session $search_data["products"]["sort_direction"] = $sort_direction; $flag_save = true; } if($current_area == 'C' && !empty($config['Appearance']['products_order']) && empty($search_data["products"]["sort_field"])) { $search_data["products"]["sort_field"] = $config['Appearance']['products_order']; $search_data["products"]["sort_direction"] = 0; } if (!empty($page) and $search_data["products"]["page"] != intval($page)) { # Store the current page number in the session $search_data["products"]["page"] = $page; $flag_save = true; } if (is_array($search_data["products"])) { $data = $search_data["products"]; foreach ($data as $k=>$v) if (!is_array($v) && !is_numeric($v)) $data[$k] = addslashes($v); } if(!isset($condition) || (isset($HTTP_GET_VARS['condition']) || isset($HTTP_POST_VARS['condition']) || isset($HTTP_COOKIE_VARS['condition']))) $condition = array(); if(!isset($join) || (isset($HTTP_GET_VARS['join']) || isset($HTTP_POST_VARS['join']) || isset($HTTP_COOKIE_VARS['join']))) $join = array(); if(!isset($add_fields) || (isset($HTTP_GET_VARS['add_fields']) || isset($HTTP_POST_VARS['add_fields']) || isset($HTTP_COOKIE_VARS['add_fields']))) $add_fields = array(); if(!isset($having) || (isset($HTTP_GET_VARS['having']) || isset($HTTP_POST_VARS['having']) || isset($HTTP_COOKIE_VARS['having']))) $having = array(); if(!isset($from_tbl) || (isset($HTTP_GET_VARS['from_tbl']) || isset($HTTP_POST_VARS['from_tbl']) || isset($HTTP_COOKIE_VARS['from_tbl']))) $from_tbl = array(); if(!isset($search_condition) || (isset($HTTP_GET_VARS['search_condition']) || isset($HTTP_POST_VARS['search_condition']) || isset($HTTP_COOKIE_VARS['search_condition']))) $search_condition = ""; $search_condition .= "$sql_tbl[pricing].productid=$sql_tbl[products].productid AND $sql_tbl[pricing].quantity=1 AND $sql_tbl[pricing].membership IN ('".addslashes(@$user_account['membership'])."','')"; if ($current_area == 'C' && empty($active_modules['Product_Configurator'])) { $search_condition .= " AND $sql_tbl[products].product_type <> 'C' AND $sql_tbl[products].product_type <> 'B' "; } $search_condition .= " AND $sql_tbl[pricing].variantid = 0"; $data["substring"] = trim($data["substring"]); if (!empty($data["substring"])) { if (empty($data["by_title"]) && empty($data["by_shortdescr"]) && empty($data["by_fulldescr"]) && empty($data["extra_fields"])) { $search_data["products"]["by_title"] = $data["by_title"] = "Y"; $flag_save = true; } # Search for substring in some fields... $search_words=explode(" ", $data["substring"]); // This separates the string by words - LNJ if (!empty($data["by_title"])) { if($current_area == 'C' || $current_area == 'P') { //$condition[] = "IF($sql_tbl[products_lng].product IS NOT NULL AND $sql_tbl[products_lng].product != '', $sql_tbl[products_lng].product, $sql_tbl[products].product) LIKE '%".$data["substring"]."%'"; foreach($search_words as $search_word){ // Loop through adding the search words - LNJ $condition[]="$sql_tbl[products].product LIKE '%".$search_word."%'"; } } else { $condition[] = "$sql_tbl[products].product LIKE '%".$data["substring"]."%'"; } } if (!empty($data["by_shortdescr"])) { if($current_area == 'C' || $current_area == 'P') { //$condition[] = "IF($sql_tbl[products_lng].descr IS NOT NULL AND $sql_tbl[products_lng].descr != '', $sql_tbl[products_lng].descr, $sql_tbl[products].descr) LIKE '%".$data["substring"]."%'"; foreach($search_words as $search_word){ // Loop through adding the search words - LNJ $condition[]="$sql_tbl[products].descr LIKE '%".$search_word."%'"; } } else { $condition[] = "$sql_tbl[products].descr LIKE '%".$data["substring"]."%'"; } } if (!empty($data["by_fulldescr"])) { if($current_area == 'C' || $current_area == 'P') { //$condition[] = "IF($sql_tbl[products_lng].full_descr IS NOT NULL AND $sql_tbl[products_lng].full_descr != '', $sql_tbl[products_lng].full_descr, $sql_tbl[products].fulldescr) LIKE '%".$data["substring"]."%'"; foreach($search_words as $search_word){ // Loop through adding the search words - LNJ $condition[]="$sql_tbl[products].fulldescr LIKE '%".$search_word."%'"; } } else { $condition[] = "$sql_tbl[products].fulldescr LIKE '%".$data["substring"]."%'"; } } if (!empty($data["extra_fields"]) && $active_modules['Extra_Fields']) { foreach($data["extra_fields"] as $k => $v) $condition[] = "($sql_tbl[extra_field_values].value LIKE '%".$data["substring"]."%' AND $sql_tbl[extra_fields].fieldid = '$k')"; $join['extra_field_values'] = "$sql_tbl[products].productid = $sql_tbl[extra_field_values].productid"; $join['extra_fields'] = "$sql_tbl[extra_field_values].fieldid = $sql_tbl[extra_fields].fieldid AND $sql_tbl[extra_fields].active = 'Y'"; } if (!empty($condition)) $search_condition .= " AND (".implode(" OR ", $condition).")"; # Search statistics db_query("INSERT INTO $sql_tbl[stats_search] (search, date) VALUES ('$data[substring]', '".time()."')"); } # /if (!empty($data["substring"])) # # Search by product features # if(!empty($active_modules['Feature_Comparison'])) { include $xcart_dir."/modules/Feature_Comparison/search_define.php"; } # # Internation names & descriptions # if($current_area == 'C' || $current_area == 'P') { $add_fields[] = "$sql_tbl[products_lng].product as product_lng"; $add_fields[] = "$sql_tbl[products_lng].descr as descr_lng"; $add_fields[] = "$sql_tbl[products_lng].full_descr as fulldescr_lng"; $join['products_lng'] = "$sql_tbl[products_lng].productid = $sql_tbl[products].productid AND $sql_tbl[products_lng].code = '$shop_language'"; } if(!empty($data["manufacturers"]) && $active_modules['Manufacturers']) { $search_condition .= " AND $sql_tbl[products].manufacturerid IN ('".implode("','", $data["manufacturers"])."')"; } $search_condition .= " AND $sql_tbl[products_categories].productid=$sql_tbl[products].productid AND $sql_tbl[products_categories].categoryid = $sql_tbl[categories].categoryid"; if($current_area == 'C') { $search_condition .= " AND $sql_tbl[categories].membership IN ('','".addslashes(@$user_account['membership'])."') AND $sql_tbl[categories].avail = 'Y'"; } $from_tbl[$sql_tbl["products_categories"]] = 1; $from_tbl[$sql_tbl["categories"]] = 1; if (!empty($data["categoryid"])) { # Search by category... $data["categoryid"] = intval($data["categoryid"]); $category_sign = ""; if (empty($data["category_main"]) && empty($data["category_extra"])) { $category_sign = "NOT"; } if (!empty($data["search_in_subcategories"])) { # Search also in all subcategories $categoryid_path = addslashes(func_query_first_cell("SELECT categoryid_path FROM $sql_tbl[categories] WHERE categoryid='".$data["categoryid"]."'")); $categoryids_tmp = func_query("SELECT categoryid FROM $sql_tbl[categories] WHERE categoryid='".$data["categoryid"]."' OR categoryid_path LIKE '$categoryid_path/%'"); if (is_array($categoryids_tmp) && !empty($categoryids_tmp)) { foreach ($categoryids_tmp as $k=>$v) { $categoryids[] = $v["categoryid"]; } $search_condition .= " AND $sql_tbl[products_categories].categoryid $category_sign IN (".implode(",", $categoryids).")"; } } else { $search_condition .= " AND $category_sign $sql_tbl[products_categories].categoryid='$data[categoryid]'"; } $condition = array(); if (!empty($data["category_main"])) $condition[] = "$sql_tbl[products_categories].main='Y'"; if (!empty($data["category_extra"])) $condition[] = "$sql_tbl[products_categories].main!='Y'"; if (!empty($condition)) $search_condition .= " AND (".implode(" OR ", $condition).")"; } elseif($current_area == 'C') { } # /if (!empty($data["categoryid"])) if (!empty($data["productcode"])) { if(!empty($active_modules['Product_Options'])) { $search_condition .= " AND ($sql_tbl[products].productcode LIKE '%".$data["productcode"]."%' OR $sql_tbl[variants].productcode LIKE '%".$data["productcode"]."%')"; } else { $search_condition .= " AND $sql_tbl[products].productcode LIKE '%".$data["productcode"]."%'"; } } if (!empty($data["productid"])) { $search_condition .= " AND $sql_tbl[products].productid ".(is_array($data["productid"]) ? " IN ('".implode("','", $data["productid"])."')": "= '".$data["productid"]."'"); } if (!empty($data["provider"])) $search_condition .= " AND $sql_tbl[products].provider='".$data["provider"]."'"; if (!empty($data["price_min"])) { if(!empty($active_modules['Product_Options'])) { $having[] = "(price>='".$data["price_min"]."' OR v_price>='".$data["price_min"]."')"; } else { $search_condition .= " AND $sql_tbl[pricing].price>='".$data["price_min"]."'"; } } if (strlen(@$data["price_max"]) > 0) { if(!empty($active_modules['Product_Options'])) { $having[] = "(price<='".$data["price_max"]."' OR v_price<='".$data["price_max"]."')"; } else { $search_condition .= " AND $sql_tbl[pricing].price<='".$data["price_max"]."'"; } } if (!empty($data["avail_min"])) { if(!empty($active_modules['Product_Options'])) { $search_condition .= " AND ($sql_tbl[products].avail>='".$data["avail_min"]."' OR $sql_tbl[variants].avail>='".$data["avail_min"]."')"; } else { $search_condition .= " AND $sql_tbl[products].avail>='".$data["avail_min"]."'"; } } if (strlen(@$data["avail_max"]) > 0) { if(!empty($active_modules['Product_Options'])) { $search_condition .= " AND ($sql_tbl[products].avail<='".$data["avail_max"]."' OR $sql_tbl[variants].avail<='".$data["avail_max"]."')"; } else { $search_condition .= " AND $sql_tbl[products].avail<='".$data["avail_max"]."'"; } } if (!empty($data["weight_min"])) { if(!empty($active_modules['Product_Options'])) { $search_condition .= " AND ($sql_tbl[products].weight>='".$data["weight_min"]."' OR $sql_tbl[variants].weight>='".$data["weight_min"]."')"; } else { $search_condition .= " AND $sql_tbl[products].weight>='".$data["weight_min"]."'"; } } if (strlen(@$data["weight_max"]) > 0) { if(!empty($active_modules['Product_Options'])) { $search_condition .= " AND ($sql_tbl[products].weight<='".$data["weight_max"]."' OR $sql_tbl[variants].weight<='".$data["weight_max"]."')"; } else { $search_condition .= " AND $sql_tbl[products].weight<='".$data["weight_max"]."'"; } } if (!empty($data["forsale"])) $search_condition .= " AND $sql_tbl[products].forsale='".$data["forsale"]."'"; if (!empty($data["flag_free_ship"])) $search_condition .= " AND $sql_tbl[products].free_shipping='".$data["flag_free_ship"]."'"; if (!empty($data["flag_ship_freight"])) $search_condition .= " AND $sql_tbl[products].shipping_freight='".$data["flag_ship_freight"]."'"; if (!empty($data["flag_ship_freight"])) { if ($data["flag_ship_freight"] == "Y") $search_condition .= " AND $sql_tbl[products].shipping_freight>'0'"; else $search_condition .= " AND $sql_tbl[products].shipping_freight='0'"; } if (!empty($data["flag_global_disc"])) $search_condition .= " AND $sql_tbl[products].discount_avail='".$data["flag_global_disc"]."'"; if (!empty($data["flag_free_tax"])) $search_condition .= " AND $sql_tbl[products].free_tax='".$data["flag_free_tax"]."'"; if (!empty($data["flag_min_amount"])) { if ($data["flag_min_amount"] == "Y") $search_condition .= " AND $sql_tbl[products].min_amount!='1'"; else $search_condition .= " AND $sql_tbl[products].min_amount='1'"; } if (!empty($data["flag_low_avail_limit"])) { if ($data["flag_low_avail_limit"] == "Y") $search_condition .= " AND $sql_tbl[products].low_avail_limit!='10'"; else $search_condition .= " AND $sql_tbl[products].low_avail_limit='10'"; } if (!empty($data["flag_list_price"])) { if ($data["flag_list_price"] == "Y") $search_condition .= " AND $sql_tbl[products].list_price!='0'"; else $search_condition .= " AND $sql_tbl[products].list_price='0'"; } if (!empty($data["flag_vat"])) { if ($data["flag_vat"] == "Y") $search_condition .= " AND $sql_tbl[products].vat!='0'"; else $search_condition .= " AND $sql_tbl[products].vat='0'"; } if (!empty($data["flag_gstpst"])) { if ($data["flag_gstpst"] == "Y") $search_condition .= " AND ($sql_tbl[products].apply_gst='Y' OR $sql_tbl[products].apply_pst='Y')"; else $search_condition .= " AND $sql_tbl[products].apply_gst='N' AND $sql_tbl[products].apply_pst='N'"; } if(!empty($active_modules['Product_Options'])) { $join['classes'] = "$sql_tbl[classes].productid = $sql_tbl[products].productid"; $join["variants"] = "$sql_tbl[variants].productid = $sql_tbl[products].productid"; if($current_area == 'C' && $config["General"]["disable_outofstock_products"] == "Y") { $join["variants"] .= " AND $sql_tbl[variants].avail > 0"; } $join["pricing v_pricing"] = "v_pricing.variantid = $sql_tbl[variants].variantid AND v_pricing.quantity = 1 AND v_pricing.membership IN ('','".addslashes(@$user_account['membership'])."')"; $add_fields[] = "IF($sql_tbl[variants].variantid IS NOT NULL,'Y','') as is_variant"; $add_fields[] = "IF($sql_tbl[classes].classid IS NOT NULL,'Y','') as is_product_options"; $add_fields[] = "MIN(v_pricing.price) as v_price"; } if (!empty($data["sort_field"])) { # Sort the search results... $direction = ($data["sort_direction"] ? "DESC" : "ASC"); switch ($data["sort_field"]) { case "productcode": $sort_string = "$sql_tbl[products].productcode $direction"; break; case "title": $sort_string = "searchscore desc, $sql_tbl[products].product $direction"; // Add score to sort - LNJ break; case "orderby": $sort_string = "$sql_tbl[products_categories].orderby $direction"; break; case "quantity": $sort_string = "$sql_tbl[products].avail $direction"; break; case "price": if (!empty($active_modules["Special_Offers"]) && !empty($search_data["products"]["show_special_prices"])) { $sort_string = "x_special_price $direction, price $direction"; } else { $sort_string = "price $direction"; } break; default: $sort_string = "searchscore desc,$sql_tbl[products].product"; // Add score to sort - LNJ } } else { $sort_string = "searchscore desc,$sql_tbl[products].product"; // Add score to sort - LNJ } if(!empty($data['sort_condition'])) { $sort_string = $data['sort_condition']; } if (($current_area == "C" || $current_area == "B") && $config["General"]["disable_outofstock_products"] == "Y") { $search_condition .= " AND ($sql_tbl[products].avail>0 OR $sql_tbl[products].product_type NOT IN ('','N')) "; } if (!empty($from_tbl) and is_array($from_tbl)) $from_tbl = ", ".implode(", ", array_keys($from_tbl)); # # Generate LEFT JOIN string # $join_string = ''; if(!empty($join) && @is_array($join)) { foreach($join as $k => $v) { list($name, $as) = explode(" ", $k); if(!empty($as)) $as = " as ".$as; $join_string .= " LEFT JOIN ".$sql_tbl[$name].$as." ON $v "; } } # # Generate HAVING string # $having_string = ''; if(!empty($having)) { $having_string = " HAVING ".implode(" AND ", $having); } # # Generate additional fields string # $add_fields_string = ''; $scorestr=""; // Add score to fields - LNJ if (!empty($data["by_title"]) && count($search_words)>0) { $scorestr.="if($sql_tbl[products].product like '%". $data["substring"] ."%',5,0) + "; //Add high score for exact match - LNJ $topscore=4; // Yeah I know HARDCODED - LNJ $scoredesc=$topscore/count($search_words); //Get decrementing number for scores - LNJ foreach($search_words as $search_word){ $scorestr.="if($sql_tbl[products].product like '%". $search_word ."%',$topscore,0) + "; //add individual word score - LNJ $topscore=$topscore-$scoredesc; //Descrement individual score for word - LNJ } } if (!empty($data["by_shortdescr"]) && count($search_words)>0) { $scorestr.="if($sql_tbl[products].descr like '%". $data["substring"] ."%',3,0) + "; //Add high score for exact match - LNJ $topscore=2; $scoredesc=$topscore/count($search_words); //Get decrementing number for scores - LNJ foreach($search_words as $search_word){ $scorestr.="if($sql_tbl[products].descr like '%". $search_word ."%',$topscore,0) + "; //add individual word score - LNJ $topscore=$topscore-$scoredesc;//Descrement individual score for word - LNJ } } if (!empty($data["by_longdescr"]) && count($search_words)>0) { $scorestr.="if($sql_tbl[products].fulldescr like '%". $data["substring"] ."%',3,0) + "; //Add high score for exact match - LNJ $topscore=2; $scoredesc=$topscore/count($search_words); //Get decrementing number for scores - LNJ foreach($search_words as $search_word){ $scorestr.="if($sql_tbl[products].fulldescr like '%". $search_word ."%',$topscore,0) + "; //add individual word score - LNJ $topscore=$topscore-$scoredesc;//Descrement individual score for word - LNJ } } $add_fields[]=$scorestr . " 0 as searchscore"; // Add this field to the list - LNJ if(!empty($add_fields) && @is_array($add_fields)) { $add_fields_string = ", ".implode(", ", $add_fields); } # # Calculate the number of rows in the search results # db_query("SET OPTION SQL_BIG_SELECTS=1"); $_res = db_query("SELECT COUNT($sql_tbl[products].productid), MIN($sql_tbl[pricing].price) as price $add_fields_string FROM $sql_tbl[products], $sql_tbl[pricing] $from_tbl $join_string WHERE $search_condition GROUP BY $sql_tbl[products].productid $having_string"); $total_items = db_num_rows($_res); db_free_result($_res); if ($total_items > 0) { $page = $search_data["products"]["page"]; # # Prepare the page navigation # if(!isset($objects_per_page)) { if ($current_area == "C" || $current_area == "B") $objects_per_page = $config["Appearance"]["products_per_page"]; else $objects_per_page = $config["Appearance"]["products_per_page_admin"]; } $total_nav_pages = ceil($total_items/$objects_per_page)+1; include $xcart_dir."/include/navigation.php"; # # Perform the SQL query and getting the search results # if (!empty($search_data["is_modify"])) { # # Get the products and go to modify them # $products = func_query("SELECT $sql_tbl[products].productid, MIN($sql_tbl[pricing].price) as price $add_fields_string FROM $sql_tbl[products], $sql_tbl[pricing] $from_tbl $join_string WHERE $search_condition GROUP BY $sql_tbl[products].productid $having_string"); if (is_array($products)) { x_session_register("store_productids"); $store_productids = array(); foreach($products as $v) $store_productids[$v['productid']] = true; func_header_location("product_modify.php?mode=return"); } } else $products = func_query("SELECT $sql_tbl[products].*, MIN($sql_tbl[pricing].price) as price $add_fields_string FROM $sql_tbl[products], $sql_tbl[pricing] $from_tbl $join_string WHERE $search_condition GROUP BY $sql_tbl[products].productid $having_string ORDER BY $sort_string, $sql_tbl[products].product ASC LIMIT $first_page, $objects_per_page"); if (!empty($products) and ($current_area == "C" || $current_area == "B")) { x_session_register("cart"); foreach ($products as $k=>$v) { if($v['is_variant'] == 'Y') { $in_cart_variants = array(); $in_cart_where = ", $sql_tbl[variants].avail"; if(!empty($cart['products'])) { foreach($cart['products'] as $cv) { if($cv['productid'] == $v['productid']) { $in_cart_variants[func_get_variantid($cv['options'])] = $cv['amount']; } } } if(!empty($in_cart_variants)) { $in_cart_where = ", ($sql_tbl[variants].avail-(CASE $sql_tbl[variants].variantid"; foreach($in_cart_variants as $kv => $vv) { $in_cart_where .= " WHEN $kv THEN $vv"; } $in_cart_where .= " ELSE 0 END)) as avail"; } $variant_cnt = intval(func_query_first_cell("SELECT COUNT(*) FROM $sql_tbl[classes] WHERE productid = '$v[productid]' AND is_modifier = ''")); $var_ex = func_create_hash_keys(func_query("SELECT $sql_tbl[variants].variantid, MIN($sql_tbl[pricing].price) as price $in_cart_where FROM $sql_tbl[pricing], $sql_tbl[variants], $sql_tbl[variant_items], $sql_tbl[class_options], $sql_tbl[classes] LEFT JOIN $sql_tbl[product_options_ex] ON $sql_tbl[class_options].optionid = $sql_tbl[product_options_ex].optionid WHERE $sql_tbl[pricing].quantity = 1 AND $sql_tbl[pricing].membership = '' AND $sql_tbl[pricing].variantid = $sql_tbl[variants].variantid AND $sql_tbl[variants].variantid = $sql_tbl[variant_items].variantid AND $sql_tbl[variant_items].optionid = $sql_tbl[class_options].optionid AND $sql_tbl[class_options].classid = $sql_tbl[classes].classid AND $sql_tbl[class_options].avail = 'Y' AND $sql_tbl[classes].avail = 'Y' AND $sql_tbl[pricing].productid = '$v[productid]' GROUP BY $sql_tbl[product_options_ex].exceptionid, $sql_tbl[pricing].variantid HAVING SUM(IF($sql_tbl[product_options_ex].optionid IS NULL, 0, 1)) = '$variant_cnt' ".(($config["General"]["disable_outofstock_products"] == "Y") ? " AND avail > 0" : "")), "variantid"); $var_ex = (empty($var_ex) ? array() : array_keys($var_ex)); $var = func_query_first("SELECT $sql_tbl[variants].variantid, $sql_tbl[variants].weight, $sql_tbl[variants].productcode, MIN($sql_tbl[pricing].price) as price $in_cart_where FROM $sql_tbl[pricing], $sql_tbl[variants], $sql_tbl[variant_items], $sql_tbl[class_options], $sql_tbl[classes] WHERE $sql_tbl[pricing].quantity = 1 AND $sql_tbl[pricing].membership = '' AND $sql_tbl[pricing].variantid = $sql_tbl[variants].variantid AND $sql_tbl[variants].variantid = $sql_tbl[variant_items].variantid AND $sql_tbl[variant_items].optionid = $sql_tbl[class_options].optionid AND $sql_tbl[class_options].classid = $sql_tbl[classes].classid AND $sql_tbl[class_options].avail = 'Y' AND $sql_tbl[classes].avail = 'Y' AND $sql_tbl[pricing].productid = '$v[productid]' AND $sql_tbl[variants].variantid NOT IN ('".implode("','", $var_ex)."') GROUP BY $sql_tbl[pricing].variantid ".(($config["General"]["disable_outofstock_products"] == "Y") ? " HAVING avail > 0" : "")." ORDER BY price LIMIT 1"); if(empty($var) && $config["General"]["disable_outofstock_products"] == "Y") { $var = func_query_first("SELECT $sql_tbl[variants].variantid, $sql_tbl[variants].weight, $sql_tbl[variants].productcode, MIN($sql_tbl[pricing].price) as price $in_cart_where FROM $sql_tbl[pricing], $sql_tbl[variants], $sql_tbl[variant_items], $sql_tbl[class_options], $sql_tbl[classes] WHERE $sql_tbl[pricing].quantity = 1 AND $sql_tbl[pricing].membership = '' AND $sql_tbl[pricing].variantid = $sql_tbl[variants].variantid AND $sql_tbl[variants].variantid = $sql_tbl[variant_items].variantid AND $sql_tbl[variant_items].optionid = $sql_tbl[class_options].optionid AND $sql_tbl[class_options].classid = $sql_tbl[classes].classid AND $sql_tbl[class_options].avail = 'Y' AND $sql_tbl[classes].avail = 'Y' AND $sql_tbl[pricing].productid = '$v[productid]' AND $sql_tbl[variants].variantid NOT IN ('".implode("','", $var_ex)."') GROUP BY $sql_tbl[pricing].variantid ORDER BY price LIMIT 1"); } if(!empty($var)) { $v = func_array_merge($v, $var); $products[$k] = $v; } } if($v['is_product_options']) { $poptions = func_query("SELECT MIN(IF($sql_tbl[class_options].modifier_type = '%', ".$v['price']."*$sql_tbl[class_options].price_modifier/100, $sql_tbl[class_options].price_modifier)) as add_price FROM $sql_tbl[classes], $sql_tbl[class_options] WHERE $sql_tbl[classes].productid = '$v[productid]' AND $sql_tbl[classes].classid = $sql_tbl[class_options].classid AND $sql_tbl[classes].is_modifier = 'Y' AND $sql_tbl[classes].avail = 'Y' GROUP BY $sql_tbl[classes].classid ORDER BY add_price"); if(!empty($poptions)) { foreach($poptions as $po) { $v['price'] += $po['add_price']; } $products[$k] = $v; } } if(!empty($active_modules['Feature_Comparison'])) { $products[$k]['is_clist'] = func_check_comparison($v['productid']); } $in_cart = 0; if(!empty($cart['products']) && $v['is_variant'] != 'Y') { foreach($cart['products'] as $cv) { if($cv['productid'] == $v['productid']) $in_cart += $cv['amount']; } $products[$k]['avail'] -= $in_cart; } if($products[$k]['avail'] < 0) { $products[$k]['avail'] = 0; } $products[$k]["tmbn_url"] = func_get_thumbnail_url($v["productid"]); if(!empty($v['product_lng'])) $products[$k]['product'] = $v['product_lng']; if(!empty($v['descr_lng'])) $products[$k]['descr'] = $v['descr_lng']; if(!empty($v['fulldescr_lng'])) $products[$k]['fulldescr'] = $v['fulldescr_lng']; unset($products[$k]['product_lng'], $products[$k]['descr_lng'], $products[$k]['fulldescr_lng']); if (!empty($active_modules["Special_Offers"]) && !empty($search_data["products"]["show_special_prices"])) { include $xcart_dir."/modules/Special_Offers/search_results_calculate.php"; } else { $products[$k]["taxes"] = func_get_product_taxes($products[$k], $login); } if($products[$k]['descr'] == strip_tags($products[$k]['descr'])) $products[$k]['descr'] = str_replace("\n"," ",$products[$k]['descr']); if($products[$k]['fulldescr'] == strip_tags($products[$k]['fulldescr'])) $products[$k]['fulldescr'] = str_replace("\n"," ",$products[$k]['fulldescr']); } if (!empty($active_modules["Special_Offers"]) && empty($search_data["products"]["show_special_prices"])) { func_offers_check_products($login, $current_area, $products); } } # Assign the Smarty variables $smarty->assign("navigation_script","search.php?mode=search"); $smarty->assign("products", $products); $smarty->assign("first_item", $first_page+1); $smarty->assign("last_item", min($first_page+$objects_per_page, $total_items)); } $smarty->assign("total_items",$total_items); $smarty->assign("mode", $mode); if ($flag_save) x_session_save("search_data"); } if (empty($search_data["products"]) && $current_area == 'C') { $search_data["products"]['productcode'] = $config['Search_products']['search_products_sku_d']; $search_data["products"]['price_min'] = preg_replace("/-.*$/", "", $config['Search_products']['search_products_price_d']); $search_data["products"]['price_max'] = preg_replace("/^.*-/", "", $config['Search_products']['search_products_price_d']); $search_data["products"]['weight_min'] = preg_replace("/-.*$/", "", $config['Search_products']['search_products_weight_d']); $search_data["products"]['weight_max'] = preg_replace("/^.*-/", "", $config['Search_products']['search_products_weight_d']); $search_data["products"]['categoryid'] = $config['Search_products']['search_products_category_d']; } if (!empty($active_modules['Feature_Comparison']) && $current_area != 'C' && $current_area != 'P') { $fclasses = func_query("SELECT $sql_tbl[feature_classes].*, IF($sql_tbl[feature_classes_lng].class IS NOT NULL, $sql_tbl[feature_classes_lng].class, $sql_tbl[feature_classes].class) as class FROM $sql_tbl[feature_classes] LEFT JOIN $sql_tbl[feature_classes_lng] ON $sql_tbl[feature_classes].fclassid = $sql_tbl[feature_classes_lng].fclassid AND $sql_tbl[feature_classes_lng].code = '$shop_language' WHERE $sql_tbl[feature_classes].avail = 'Y' ORDER BY $sql_tbl[feature_classes].orderby"); if(!empty($fclasses)) { $smarty->assign("fclasses", $fclasses); } } $smarty->assign("search_prefilled", $search_data["products"]); if($active_modules['Manufacturers']) { $manufacturers = func_query("SELECT * FROM $sql_tbl[manufacturers] WHERE avail = 'Y' ORDER BY orderby,manufacturer"); if($manufacturers) { array_unshift($manufacturers, array("manufacturerid" => '0', "manufacturer" => func_get_langvar_by_name("lbl_no_manufacturer"))); $tmp = explode("\n", $config['Search_products']['search_products_manufacturers_d']); foreach($manufacturers as $k => $v) { if(@in_array($v['manufacturerid'], (array)$search_data["products"]['manufacturers']) || (in_array($v['manufacturerid'], $tmp) && $current_area == 'C')) $manufacturers[$k]['selected'] = 'Y'; } if($manufacturers) $smarty->assign("manufacturers", $manufacturers); } } if($active_modules['Extra_Fields']) { $extra_fields = func_query("SELECT * FROM $sql_tbl[extra_fields] WHERE active = 'Y' ORDER BY field"); if($extra_fields) { $tmp = explode("\n", $config['Search_products']['search_products_extra_fields']); foreach($extra_fields as $k => $v) { if(!in_array($v['fieldid'], $tmp) && $current_area == 'C') { unset($extra_fields[$k]); continue; } if($search_data["products"]['extra_fields'][$v['fieldid']]) $extra_fields[$k]['selected'] = 'Y'; } if($extra_fields) $smarty->assign("extra_fields", $extra_fields); } } if ($current_area != 'C') include_once $xcart_dir."/include/categories.php"; $search_categories = $smarty->get_template_vars("allcategories"); if ($current_area == "C" && !empty($active_modules["Fancy_Categories"])) { if(!function_exists("func_categories_sort_abc")) { function func_categories_sort_abc($a, $b) { return strcmp($a["category_path"], $b["category_path"]); } } usort($search_categories, "func_categories_sort_abc"); } $smarty->assign("search_categories", $search_categories); unset($search_categories); if (!defined('IS_ROBOT')) $smarty->assign("sort_fields", $sort_fields); $smarty->assign("main","search"); $from_tbl = $condition = $join = $add_fields = $having = array(); $search_condition = ""; unset($from_tbl, $condition, $join, $add_fields, $having, $search_condition); ?>
__________________
  • X-Cart Version 4.1
  • PHP Version 4.4.x eAccelerator
  • MySQL 4.1
  • Fedora Core 1
  • Dual Xeon 2.4Ghz Hyperthreading enabled 2GB Ram
Reply With Quote
  #154  
Old 09-29-2005, 02:52 PM
 
Don L Don L is offline
 

Member
  
Join Date: Sep 2005
Posts: 27
 

Default

Code works like a champ for me on a 4.0.16 install. Good solution!
__________________
GetItCheap.com
x-cart v4.0.17

TheNewDonald.com - Internet Marketing Blog
Reply With Quote
  #155  
Old 09-30-2005, 05:15 AM
 
colonial123 colonial123 is offline
 

Senior Member
  
Join Date: Jun 2005
Location: NH
Posts: 145
 

Default

Works on my version. Good job!
__________________
William McCoy
Online Manager
Colonial Medical
Version 4.0.13
Reply With Quote
  #156  
Old 09-30-2005, 06:01 AM
 
Don L Don L is offline
 

Member
  
Join Date: Sep 2005
Posts: 27
 

Default

One small problem with this code is that it doesn't sort by searchscore on searches originating from a category page. Here's my alteration to make it always default to sorting by searchscore:

Comment out the case "orderby" in the sort search results section.

Commented out section:
Code:
// case "orderby": // $sort_string = "$sql_tbl[products_categories].orderby $direction"; // break;

Including surrounding code:
Code:
if (!empty($data["sort_field"])) { # Sort the search results... $direction = ($data["sort_direction"] ? "DESC" : "ASC"); switch ($data["sort_field"]) { case "productcode": $sort_string = "$sql_tbl[products].productcode $direction"; break; case "title": $sort_string = "searchscore desc, $sql_tbl[products].product $direction"; // Add score to sort - LNJ break; // case "orderby": // $sort_string = "$sql_tbl[products_categories].orderby $direction"; // break; case "quantity": $sort_string = "$sql_tbl[products].avail $direction"; break; case "price": if (!empty($active_modules["Special_Offers"]) && !empty($search_data["products"]["show_special_prices"])) { $sort_string = "x_special_price $direction, price $direction"; } else { $sort_string = "price $direction"; } break; default: $sort_string = "searchscore desc,$sql_tbl[products].product"; // Add score to sort - LNJ }

That's it. This may have unintended consequences, but none that I have encountered so far.
__________________
GetItCheap.com
x-cart v4.0.17

TheNewDonald.com - Internet Marketing Blog
Reply With Quote
  #157  
Old 09-30-2005, 07:29 AM
 
colonial123 colonial123 is offline
 

Senior Member
  
Join Date: Jun 2005
Location: NH
Posts: 145
 

Default Needs work

This is a great start but it still needs some work, Ive noticed that It gives most priority to the title as it should. However lets say im doing a search for

Motion Detector Alarms


It would bring up a product named, "Motion sickness bands" over a product called, "UMP Motion detectors - Black" Even though in the UMP motion detectors description the use of the word alarm is plastered in there too while the Motion sickness bands description does not contain the word alarm at all.

Basically it would be cool if the search engine could break up all the words in the search string (which your search engine solution currently does) and have it search the title and description for the best product that can match all the words in the string. If two products both have all the words then it would sort the product with the most keywords in the title over the other....

I am looking into coding this in, If you have any ideas let me know. I think this would be a great enhancement to this search engine...
__________________
William McCoy
Online Manager
Colonial Medical
Version 4.0.13
Reply With Quote
  #158  
Old 09-30-2005, 07:43 AM
 
Don L Don L is offline
 

Member
  
Join Date: Sep 2005
Posts: 27
 

Default

Off the top of my head, try removing the deprecating parts of the scoring and see if that fixes your problem.
__________________
GetItCheap.com
x-cart v4.0.17

TheNewDonald.com - Internet Marketing Blog
Reply With Quote
  #159  
Old 09-30-2005, 08:12 AM
 
colonial123 colonial123 is offline
 

Senior Member
  
Join Date: Jun 2005
Location: NH
Posts: 145
 

Default

I don't suppose you could show the code for that???
__________________
William McCoy
Online Manager
Colonial Medical
Version 4.0.13
Reply With Quote
  #160  
Old 09-30-2005, 08:26 AM
 
Don L Don L is offline
 

Member
  
Join Date: Sep 2005
Posts: 27
 

Default

keep in mind this is completely untested, and may not have the intended result at all:

Code:
# # Generate additional fields string # $add_fields_string = ''; $scorestr=""; // Add score to fields - LNJ if (!empty($data["by_title"]) && count($search_words)>0) { $scorestr.="if($sql_tbl[products].product like '%". $data["substring"] ."%',5,0) + "; //Add high score for exact match - LNJ $topscore=4; // Yeah I know HARDCODED - LNJ $scoredesc=$topscore/count($search_words); //Get decrementing number for scores - LNJ foreach($search_words as $search_word){ $scorestr.="if($sql_tbl[products].product like '%". $search_word ."%',$topscore,0) + "; //add individual word score - LNJ // $topscore=$topscore-$scoredesc; //Descrement individual score for word - LNJ } } if (!empty($data["by_shortdescr"]) && count($search_words)>0) { $scorestr.="if($sql_tbl[products].descr like '%". $data["substring"] ."%',3,0) + "; //Add high score for exact match - LNJ $topscore=2; $scoredesc=$topscore/count($search_words); //Get decrementing number for scores - LNJ foreach($search_words as $search_word){ $scorestr.="if($sql_tbl[products].descr like '%". $search_word ."%',$topscore,0) + "; //add individual word score - LNJ // $topscore=$topscore-$scoredesc;//Descrement individual score for word - LNJ } } if (!empty($data["by_longdescr"]) && count($search_words)>0) { $scorestr.="if($sql_tbl[products].fulldescr like '%". $data["substring"] ."%',3,0) + "; //Add high score for exact match - LNJ $topscore=2; $scoredesc=$topscore/count($search_words); //Get decrementing number for scores - LNJ foreach($search_words as $search_word){ $scorestr.="if($sql_tbl[products].fulldescr like '%". $search_word ."%',$topscore,0) + "; //add individual word score - LNJ // $topscore=$topscore-$scoredesc;//Descrement individual score for word - LNJ } } $add_fields[]=$scorestr . " 0 as searchscore"; // Add this field to the list - LNJ if(!empty($add_fields) && @is_array($add_fields)) { $add_fields_string = ", ".implode(", ", $add_fields); }
__________________
GetItCheap.com
x-cart v4.0.17

TheNewDonald.com - Internet Marketing Blog
Reply With Quote
Reply
   X-Cart forums > X-Cart 4 > Dev Questions


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump


All times are GMT -8. The time now is 04:27 PM.

   

 
X-Cart forums © 2001-2020