web-dev-qa-db-ja.com

laravelスペースで区切られた複数の単語を検索

laravelクエリビルダーを初めて使用します。たとえば、「jhon doe」と入力した場合、入力フィールドに入力された複数の単語を検索したいです。jhonまたはdoeを含む列を取得したいです。

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.'%')

助けてください、事前に感謝します

12
user4006175

これは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();

or where句を括弧で囲むことをお勧めするため、whereにはクロージャがあります。たとえば、UserモデルがSoftDeletingScopeを使用していて、私が提案したことを実行しない場合、クエリ全体が台無しになります。

28
Jarek Tkaczyk
 $keywordRaw = "jhon doe";
    $key = explode(' ',$keywordRaw)
    $users = User::select('users.*')
    ->whereIn('first_name',$key);

これは機能します。whereInは入力したキーワードから名を検索します。

3
Sameer Shaikh

これを試してください..

   $searchQuery = "jhon doe"; 
$searchTerms = explode(" ", $searchQuery); // Split the words
$users = User::whereIn('FirstName', $searchTerms)->get();
print_r($users);

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を使用する場合に当てはまります)。

allの単語を含むレコードを検索する場合は、次のように、各キーワードの前に「+」を付ける必要があります。

$keywords   = '+'.explode(' +', $keywordRaw);

関連性で並べ替えることもできますが、これはおそらくニーズには行き過ぎです(「すべての」検索には関係ありません)。このようなもの:

$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

1
sevenpointsix

次のように試すことができます

$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);
1
EthanHu
$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'を使用すると、keyword1 + keyword2の結果ではなく各キーワードの結果が得られます...したがってすべてはあなたが探しているものに依存します

0
Jerome

このパッケージを使用できます https://github.com/nicolaslopezj/searchable

または、パッケージを使用したくない場合は、これを実行してください

$keywordRaw = "jhon doe";
$users = User::where('first_name', 'LIKE', $keywordRaw.'%')
->orWhere('first_name', 'LIKE', '% '.$keywordRaw.'%')
->get();
0
C.V