laravel 搜索由 space 分隔的多个单词
laravel search multiple words separated by space
我是 laravel 查询生成器的新手,我想搜索在输入字段中输入的多个单词,例如,如果我键入 "jhon doe" 我想获取包含 jhon 或 doe[ 的任何列=14=]
我有 seen/tried 个使用 php MySQL 的解决方案,但无法适应查询构建器
//1. exploding the space between the keywords
//2. using foreach apend the query together
$query = "select * from users where";
$keywordRaw = "jhon doe";
$keywords = explode(' ', $keywordRaw );
foreach ($keywords as $keyword){
$query.= " first_name LIKE '%" + $keyword +"%' OR ";
}
我如何使用查询生成器执行此操作
这是我目前所掌握的,正确的做法是什么,
$keywordRaw = "jhon doe";
//how do I explode this words and append them along with their appropriate query
$users = User::select('users.*')
->where('first_name', 'LIKE', '%'.$keywordRaw.'%')
请帮忙,提前致谢
您可以尝试如下
$keywordRaw = "jhon doe";
$bindArr = explode(" ", $keywordRaw);
$query = "select * from users where";
foreach ($i = 0; $i < count($bindArr); $i++) {
if ($i == 0) {
$query.= ' first_name LIKE "%?%"';
} else {
$query.= ' or first_name LIKE "%?%"';
}
}
$sth = $dbh->prepare($query);
$sth->execute($bindArr);
试试这个..
$searchQuery = "jhon doe";
$searchTerms = explode(" ", $searchQuery); // Split the words
$users = User::whereIn('FirstName', $searchTerms)->get();
print_r($users);
$keywordRaw = "jhon doe";
$key = explode(' ',$keywordRaw);
$users = User::select('users.*')
->whereIn('first_name',$key);
这会 work.the whereIn 会根据您输入的关键字搜索名字。
这就是使用 Query\Builder
的方法,但首先要注意一些:
// user can provide double space by accident, or on purpose:
$string = 'john doe';
// so with explode you get this:
explode(' ', $string);
array(
0 => 'john',
1 => '',
2 => 'doe'
)
// Now if you go with LIKE '%'.value.'%', you get this:
select * from table where name like '%john%' or name like '%%' or ...
也就是说,您显然不能依赖 explode
,因为在上述情况下您会获得所有行。
所以,这是你应该做的:
$string = 'john doe';
// split on 1+ whitespace & ignore empty (eg. trailing space)
$searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY);
$users = User::where(function ($q) use ($searchValues) {
foreach ($searchValues as $value) {
$q->orWhere('name', 'like', "%{$value}%");
}
})->get();
where
中有闭包,因为最好将 or where
子句括在括号中。例如,如果您的 User
模型使用了 SoftDeletingScope
而您没有按照我的建议进行操作,那么您的整个查询就会一团糟。
您是否考虑过在 first_name 列上使用 FULLTEXT 索引?
您可以使用 Laravel 迁移创建此索引,尽管您需要使用 SQL 语句:
DB::statement('ALTER TABLE users ADD FULLTEXT(first_name);');
然后您可以 运行 针对此字段进行非常高级的搜索,如下所示:
$keywordRaw = "john doe";
$keywords = explode(' ', $keywordRaw);
$users = User::select("*")
->whereRaw("MATCH (first_name)
against (? in boolean mode)",[$keywords])
->get();
这将匹配包含单词 "john" 或 "doe" 的记录;请注意,这种方法将匹配整个单词,而不是子字符串(如果您使用 LIKE 可能会出现这种情况)。
如果你想查找包含 所有 个词的记录,你应该在每个关键字前加上一个“+”,像这样:
$keywords = '+'.explode(' +', $keywordRaw);
您甚至可以按相关性排序,尽管这可能对您的需求来说有点过分(并且与 "all" 搜索无关)。像这样:
$users = User::select("*")
->selectRaw("MATCH (first_name)
against (? in boolean mode)
AS relevance",[$keywords])
->whereRaw("MATCH (first_name)
against (? in boolean mode)",[$keywords])
->orderBy('relevance','DESC')
->get();
这里有一篇介绍这种通用方法的好文章:
http://www.hackingwithphp.com/9/3/18/advanced-text-searching-using-full-text-indexes
你可以使用这个包https://github.com/nicolaslopezj/searchable
或者如果你不想使用包就这样做
$keywordRaw = "jhon doe";
$users = User::where('first_name', 'LIKE', $keywordRaw.'%')
->orWhere('first_name', 'LIKE', '% '.$keywordRaw.'%')
->get();
$string = 'john doe';
// split on 1+ whitespace & ignore empty (eg. trailing space)
$searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY);
$users = User::where(function ($q) use ($searchValues) {
foreach ($searchValues as $value) {
$q->Where('name', 'like', "%{$value}%");
}
})->get();
使用 'orWhere' 会得到每个关键字的结果,而不是关键字 1 + 关键字 2 的结果...所以一切都取决于您要查找的内容
我在下面写了第一个解决方案并且有效
解决方案 1
function fuzzySearch($keyword='jhon doe'){
$queryText = implode('%',str_split($keyWord));
return User::query()->where('first_name','LIKE',"%{$queryText}%")->get();
}
但是,当我在搜索中添加空格时,returns 为空结果,但它们存在于数据库中,所以我添加了 str_replace(" ","",$keyWord)
来删除空格,现在可以使用了
解决方案 2
function fuzzySearch($keyword='jhon doe'){
$queryText = implode('%',str_split(str_replace(" ","",$keyWord)));
return User::query()->where('first_name','LIKE',"%{$queryText}%")->get();
}
NOTE implode()
函数将关键字 jhon doe 转换为 j%h%o%n%d%o%e
我是 laravel 查询生成器的新手,我想搜索在输入字段中输入的多个单词,例如,如果我键入 "jhon doe" 我想获取包含 jhon 或 doe[ 的任何列=14=]
我有 seen/tried 个使用 php MySQL 的解决方案,但无法适应查询构建器
//1. exploding the space between the keywords
//2. using foreach apend the query together
$query = "select * from users where";
$keywordRaw = "jhon doe";
$keywords = explode(' ', $keywordRaw );
foreach ($keywords as $keyword){
$query.= " first_name LIKE '%" + $keyword +"%' OR ";
}
我如何使用查询生成器执行此操作
这是我目前所掌握的,正确的做法是什么,
$keywordRaw = "jhon doe";
//how do I explode this words and append them along with their appropriate query
$users = User::select('users.*')
->where('first_name', 'LIKE', '%'.$keywordRaw.'%')
请帮忙,提前致谢
您可以尝试如下
$keywordRaw = "jhon doe";
$bindArr = explode(" ", $keywordRaw);
$query = "select * from users where";
foreach ($i = 0; $i < count($bindArr); $i++) {
if ($i == 0) {
$query.= ' first_name LIKE "%?%"';
} else {
$query.= ' or first_name LIKE "%?%"';
}
}
$sth = $dbh->prepare($query);
$sth->execute($bindArr);
试试这个..
$searchQuery = "jhon doe";
$searchTerms = explode(" ", $searchQuery); // Split the words
$users = User::whereIn('FirstName', $searchTerms)->get();
print_r($users);
$keywordRaw = "jhon doe";
$key = explode(' ',$keywordRaw);
$users = User::select('users.*')
->whereIn('first_name',$key);
这会 work.the whereIn 会根据您输入的关键字搜索名字。
这就是使用 Query\Builder
的方法,但首先要注意一些:
// user can provide double space by accident, or on purpose:
$string = 'john doe';
// so with explode you get this:
explode(' ', $string);
array(
0 => 'john',
1 => '',
2 => 'doe'
)
// Now if you go with LIKE '%'.value.'%', you get this:
select * from table where name like '%john%' or name like '%%' or ...
也就是说,您显然不能依赖 explode
,因为在上述情况下您会获得所有行。
所以,这是你应该做的:
$string = 'john doe';
// split on 1+ whitespace & ignore empty (eg. trailing space)
$searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY);
$users = User::where(function ($q) use ($searchValues) {
foreach ($searchValues as $value) {
$q->orWhere('name', 'like', "%{$value}%");
}
})->get();
where
中有闭包,因为最好将 or where
子句括在括号中。例如,如果您的 User
模型使用了 SoftDeletingScope
而您没有按照我的建议进行操作,那么您的整个查询就会一团糟。
您是否考虑过在 first_name 列上使用 FULLTEXT 索引?
您可以使用 Laravel 迁移创建此索引,尽管您需要使用 SQL 语句:
DB::statement('ALTER TABLE users ADD FULLTEXT(first_name);');
然后您可以 运行 针对此字段进行非常高级的搜索,如下所示:
$keywordRaw = "john doe";
$keywords = explode(' ', $keywordRaw);
$users = User::select("*")
->whereRaw("MATCH (first_name)
against (? in boolean mode)",[$keywords])
->get();
这将匹配包含单词 "john" 或 "doe" 的记录;请注意,这种方法将匹配整个单词,而不是子字符串(如果您使用 LIKE 可能会出现这种情况)。
如果你想查找包含 所有 个词的记录,你应该在每个关键字前加上一个“+”,像这样:
$keywords = '+'.explode(' +', $keywordRaw);
您甚至可以按相关性排序,尽管这可能对您的需求来说有点过分(并且与 "all" 搜索无关)。像这样:
$users = User::select("*")
->selectRaw("MATCH (first_name)
against (? in boolean mode)
AS relevance",[$keywords])
->whereRaw("MATCH (first_name)
against (? in boolean mode)",[$keywords])
->orderBy('relevance','DESC')
->get();
这里有一篇介绍这种通用方法的好文章:
http://www.hackingwithphp.com/9/3/18/advanced-text-searching-using-full-text-indexes
你可以使用这个包https://github.com/nicolaslopezj/searchable
或者如果你不想使用包就这样做
$keywordRaw = "jhon doe";
$users = User::where('first_name', 'LIKE', $keywordRaw.'%')
->orWhere('first_name', 'LIKE', '% '.$keywordRaw.'%')
->get();
$string = 'john doe';
// split on 1+ whitespace & ignore empty (eg. trailing space)
$searchValues = preg_split('/\s+/', $string, -1, PREG_SPLIT_NO_EMPTY);
$users = User::where(function ($q) use ($searchValues) {
foreach ($searchValues as $value) {
$q->Where('name', 'like', "%{$value}%");
}
})->get();
使用 'orWhere' 会得到每个关键字的结果,而不是关键字 1 + 关键字 2 的结果...所以一切都取决于您要查找的内容
我在下面写了第一个解决方案并且有效
解决方案 1
function fuzzySearch($keyword='jhon doe'){
$queryText = implode('%',str_split($keyWord));
return User::query()->where('first_name','LIKE',"%{$queryText}%")->get();
}
但是,当我在搜索中添加空格时,returns 为空结果,但它们存在于数据库中,所以我添加了 str_replace(" ","",$keyWord)
来删除空格,现在可以使用了
解决方案 2
function fuzzySearch($keyword='jhon doe'){
$queryText = implode('%',str_split(str_replace(" ","",$keyWord)));
return User::query()->where('first_name','LIKE',"%{$queryText}%")->get();
}
NOTE implode()
函数将关键字 jhon doe 转换为 j%h%o%n%d%o%e