在我的网站中,我需要提供一个搜索选项,用户可以在其中搜索不同的产品。现在我想如果搜索键与产品显示匹配,并显示一些建议包含该搜索关键字以空格分隔。
list($type,$search) = explode(":", $key);
$searchValues = preg_split('/\s+/', $search, -1, PREG_SPLIT_NO_EMPTY);
ProductDetail::join('product_brands','product_details.brand_id','product_brands.id')
->select('brand_name as manufacturer','product_availability as isInStock','product_details.*','product_price as displayPrice')
->where(function ($q) use ($searchValues,$search) {
$q->where('product_name', 'like', "%{$search}%");
foreach ($searchValues as $value) {
$q->orWhere('product_name', 'like', "%{$value}%");
}
})->paginate(5);
现在这个结果出现了问题,它根据最佳/第一场比赛显示。所以用户无法在其他建议列表中找到他们想要的内容。
那么如何获得最佳匹配订单?
答案 0 :(得分:2)
您需要的是某种加权搜索。如果你看看这个包,你可以看到它生成的一些示例MySQL查询:https://github.com/nicolaslopezj/searchable
滚动到“结果”部分,其中显示了它生成的结果查询。这将有助于您在最佳匹配上对结果进行加权。如果您有更深入的搜索需求,也可以查看Laravel Scout。
这是我所指的示例查询,其中此程序包用于搜索Sed neque labore
之类的用户:
select `users`.*,
-- If third parameter is set as true, it will check if the column starts with the search
-- if then it adds relevance * 30
-- this ensures that relevant results will be at top
(case when first_name LIKE 'Sed neque labore%' then 300 else 0 end) +
-- For each column you specify makes 3 "ifs" containing
-- each word of the search input and adds relevace to
-- the row
-- The first checks if the column is equal to the word,
-- if then it adds relevance * 15
(case when first_name LIKE 'Sed' || first_name LIKE 'neque' || first_name LIKE 'labore' then 150 else 0 end) +
-- The second checks if the column starts with the word,
-- if then it adds relevance * 5
(case when first_name LIKE 'Sed%' || first_name LIKE 'neque%' || first_name LIKE 'labore%' then 50 else 0 end) +
-- The third checks if the column contains the word,
-- if then it adds relevance * 1
(case when first_name LIKE '%Sed%' || first_name LIKE '%neque%' || first_name LIKE '%labore%' then 10 else 0 end) +
-- Repeats with each column
(case when last_name LIKE 'Sed' || last_name LIKE 'neque' || last_name LIKE 'labore' then 150 else 0 end) +
(case when last_name LIKE 'Sed%' || last_name LIKE 'neque%' || last_name LIKE 'labore%' then 50 else 0 end) +
(case when last_name LIKE '%Sed%' || last_name LIKE '%neque%' || last_name LIKE '%labore%' then 10 else 0 end) +
(case when bio LIKE 'Sed' || bio LIKE 'neque' || bio LIKE 'labore' then 30 else 0 end) +
(case when bio LIKE 'Sed%' || bio LIKE 'neque%' || bio LIKE 'labore%' then 10 else 0 end) +
(case when bio LIKE '%Sed%' || bio LIKE '%neque%' || bio LIKE '%labore%' then 2 else 0 end) +
(case when email LIKE 'Sed' || email LIKE 'neque' || email LIKE 'labore' then 75 else 0 end) +
(case when email LIKE 'Sed%' || email LIKE 'neque%' || email LIKE 'labore%' then 25 else 0 end) +
(case when email LIKE '%Sed%' || email LIKE '%neque%' || email LIKE '%labore%' then 5 else 0 end)
as relevance
from `users`
group by `id`
-- Selects only the rows that have more than
-- the sum of all attributes relevances and divided by 4
-- Ej: (20 + 5 + 2) / 4 = 6.75
having relevance > 6.75
-- Orders the results by relevance
order by `relevance` desc