分面搜索有些麻烦

时间:2013-11-14 10:29:54

标签: php mysql algorithm search facet

我开始在我的项目中开发方面搜索。作为示例它应该如何工作我拿了asos.com。作为引擎,我使用mysql进行全文搜索,使用sphinx进行全文搜索。为了更快地搜索,我在db中对非规范化数据进行了非规范化处理,并为此创建了特殊表。

CREATE TABLE `item_search` (
  `id` int(10) unsigned NOT NULL DEFAULT '0',
  `item_id` int(10) unsigned NOT NULL DEFAULT '0',
  `tab` tinyint(3) unsigned NOT NULL,
  `designer_id` smallint(5) unsigned NOT NULL,
  `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `price` decimal(18,2) NOT NULL,
  `arm` tinyint(3) unsigned NOT NULL,
  `bridge` tinyint(3) unsigned NOT NULL,
  `lens_width` tinyint(3) unsigned NOT NULL,
  `rating` int(11) unsigned DEFAULT '0',
  `pageviews` int(11) unsigned DEFAULT '0',
  `category_id` int(4) unsigned NOT NULL,
  KEY `index2` (`item_id`,`tab`,`price`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY LIST (tab)
(PARTITION pg VALUES IN (1) ENGINE = InnoDB,
 PARTITION rx VALUES IN (2) ENGINE = InnoDB,
 PARTITION sun VALUES IN (3) ENGINE = InnoDB,
 PARTITION acc VALUES IN (4) ENGINE = InnoDB)

如何在代码中查看。

if (Arr::get($args, 'query')){
  // Get item ids that was found by query
  $args['item_ids'] = Items::findByFullText($args);
}

...//Some code here

if ($item_ids = Arr::get($args, 'item_ids')){
  $where[] = "item_id IN (".implode(',', $item_ids).")";
}

...// Build and execute query and return item_ids

我可以在多个组中发送多个类别进行搜索。

if ($categories = Arr::get($args, 'categories')){
  // group categories by categories group
  $categories = Category::groupCategories($categories);

  foreach ($categories as $group_id => $category_group){
   foreach ($category_group as $category_id){
    $item_ids[$group_id][] = Category::getItemIdsByCategory($category_id);
   }

   // Sum all item ids by this group
   if (sizeof($item_ids[$group_id]) == 1){
    $item_ids_by_group[$group_id] = $item_ids[$group_id][0];
   }else{
    $item_ids_by_group[$group_id] = call_user_func_array('array_merge', $item_ids[$group_id]);
   }
  }

  // Return found item ids by categories
   (sizeof($item_ids_by_group) == 1)
        ? $item_ids_by_group[$group_id]
        : call_user_func_array('array_intersect', $item_ids_by_group);
}

如果为结果启用缓存,这个工作速度非常快,这里只有一个问题,就是没有可能获取像asos.do这样的类别。返回类别组的类别ID应该是什么逻辑?非常感谢您的回应。

1 个答案:

答案 0 :(得分:1)

Mysql使用B-TREE来存储索引,Lucene上的Sorl(这是一个功能强大的Java库,特别是用于搜索内容)使用术语词典和二进制搜索来表示这些术语。在Solr索引十亿个文档,花费不到1秒,用任何sql解决方案打败它。
这是一个很好的教程: http://searchhub.org/2009/09/02/faceted-search-with-solr/ 我已经测试了500万份文件并且仍然得到不到1秒的结果,这些确切的结果可以通过简单的谷歌搜索的类似经验来证明。
另外,我可以补充说,由于使用Mysql进行分面的开销,它已不再使用了。

基本上,今天作为最佳实践使用的框架是在Memcache / Solr和主Sql解决方案中编写,然后只从Solr / Memcache中读取。

这是我曾经工作的eBay副本,并使用Solr作为它的分面和搜索引擎:http://www.okazii.ro/

另外,如果你坚持使用狮身人面像,请尝试:http://www.dreamstime.com

另外,看看这个比较:

Choosing a stand-alone full-text search server: Sphinx or SOLR?

正如您所看到的:Solr带有开箱即用的小平面支撑。面对狮身人面像需要更多的工作。