【问题标题】:multiple table search laravel多表搜索 laravel
【发布时间】:2020-06-23 18:32:07
【问题描述】:

我想搜索问题帖子中的所有内容,包括问题标题、问题描述、答案、问题 cmets 和答案 cmets。
我想为这个案例做一个优化的搜索查询。

输出应该有共同的'slug'。如果关键字匹配标题、描述、答案、问题 cmets 和答案 cmets,则响应应该有点像这样..

  #items: array:3 [▼
    0 => {#2517 ▼
      +"slug": "question-slug-here"
      +"search_type": "a-comment"
      +"content": "asdfg afgnistan jjdknsfr"
    }
    1 => {#2524 ▼
      +"slug": "question-slug-here"
      +"search_type": "answer"
      +"content": "<p>fgnbk gsnpobgklkfdmlkfdjb mdfjlblfkdj hbdjsdl,g hkldjhbfdk hbopdtgh dgjnhgfm</p>"
    }
    2 => {#2518 ▼
      +"slug": "question-slug-here"
      +"search_type": "a-comment"
      +"content": "fgn again testing"
    }
    3 => {#2519 ▼
      +"slug": "question-slug-here"
      +"search_type": "title"
      +"content": "question title here which has searched keyword"
    }
    4 => {#2520 ▼
      +"slug": "question-slug-here"
      +"search_type": "q-comment"
      +"content": "matched question comment here"
    }
    5 => {#2521 ▼
      +"slug": "question-slug-here"
      +"search_type": "description"
      +"content": "matched question description here"
    }
    ....
    ....
  ]

每个问题一个标题和描述记录,但它应该有多个答案记录,一个问题的问题和答案cmets记录。

我有以下代码

$questions = DB::table('questions as q')
                ->select('slug',
                    DB::raw("(CASE 
                        WHEN title LIKE '%".$search_text."%' THEN 'title'
                        WHEN description LIKE '%".$search_text."%' THEN 'description'
                        WHEN answer LIKE '%".$search_text."%' THEN 'answer'
                        WHEN ac.comment LIKE '%".$search_text."%' THEN 'a-comment'
                        WHEN qc.comment LIKE '%".$search_text."%' THEN 'q-comment'
                        ELSE 'None'
                        END) AS search_type,

                        (CASE 
                        WHEN title LIKE '%".$search_text."%' THEN title
                        WHEN description LIKE '%".$search_text."%' THEN description
                        WHEN answer LIKE '%".$search_text."%' THEN answer
                        WHEN ac.comment LIKE '%".$search_text."%' THEN ac.comment
                        WHEN qc.comment LIKE '%".$search_text."%' THEN qc.comment
                        ELSE 'None'
                        END) AS content
                        "))
              ->leftjoin('question_answer as qa','qa.question_id','=','q.id')

              ->leftjoin('question_answer_comments as qc', function($join) {
                  $join->on('qc.commentable_id','=','q.id')
                      ->where('qc.commentable_type', '=', 'App\Models\Question');
              })
              ->leftjoin('question_answer_comments as ac', function($join1) {
                  $join1->on('ac.commentable_id','=','qa.id')
                      ->where('ac.commentable_type', '=', 'App\Models\QuestionAnswer');
              })
              
              
              ->where('q.is_active','Y')
              ->where(function ($query) use ($search_text) {
                  $query->orwhere('title','LIKE','%'.$search_text.'%')
                  ->orwhere('description','LIKE','%'.$search_text.'%')
                  ->orwhere('answer','LIKE','%'.$search_text.'%')
                  ->orwhere('ac.comment','LIKE','%'.$search_text.'%')
                  ->orwhere('qc.comment','LIKE','%'.$search_text.'%');
              })
              // ->groupBy('q.id','search_type')
              ;

dd($questions->get());

当前问题

  1. 如果关键字与标题匹配,它将多次获取一些相同的记录,而与其他搜索结果无关(它已匹配答案和 cmets,但未获取这些。我猜该错误与选择 DB Raw 相关查询)
  2. 如果关键字与标题不匹配,则它将搜索除问题 cmets 之外的所有其他关键字。如果我在选择的 DB Raw 中颠倒问题和答案评论的顺序(首先是问题评论,其次是回答评论),那么它只会显示问题 cmets ,并且有时可能会像这样显示相同问题评论数据的多个记录。

如何使用 groupBy 属性来消除重复字段。
我可以根据条件使用 addSelect 而不是 DB raw 使用案例吗?

感谢您的帮助和指导。谢谢:)

【问题讨论】:

  • 你是否在问题模型中设置了commentsanswersanswers.comments的关系形式?
  • 是的,这些型号我都有

标签: mysql laravel


【解决方案1】:

您的问题模型应具有如下关系设置:

有问题的模型Question.php

public function answers()
{
    return $this->hasMany(Answer::class);
}

public function comments()
{
    return $this->hasMany(Comment::class);
}

搜索范围为

public function scopeSearch($query, string $term)
{
    collect(explode(' ', $term))->filter()->each(function ($term) use ($query) {
        $term = '%' . $term . '%';
        $query->where('title', 'like', $term)
            ->orWhere('description', 'like', $term)
            ->orWhereHas('comments', function ($query) use ($term) {
                $query->where('body', 'like', $term); // comments body field
            })->orWhereHas('answers', function ($query) use ($term) {
                $query->where('body', 'like', $term) // answers body field
                ->orWhereHas('comments', function ($query) use ($term) {
                    $query->where('body', 'like', $term); // answer comments body field
                });
            });
    });
}

public static function scopeIsActive($query)
{
    return $query->where('is_active', 'Y');
}

在回答模型Answer.php

public function comments()
{
    return $this->hasMany(Comment::class);
}

现在你可以在控制器中搜索

$questions = Question::search($search_text)->isActive()->get();

如果您使用polymorphic 关系,请使用orWhereHasMorph

我希望,你已经明白了。如果您有任何问题,请告诉我。

【讨论】:

  • 干净整洁的解决方案!我真的很喜欢这种方法。但我的要求与此有些不同。如果它匹配其任何内部内容,这将返回问题模型。但我的要求是将每个内部元素(如描述、答案和 cmets ......)作为单独的搜索结果分开。
  • 我并没有真正理解这个要求。只是一个想法/提示,您是否检查了 addSelect reinink.ca/articles/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-03
  • 2020-03-20
  • 2018-05-16
  • 2021-02-13
  • 2013-09-30
  • 2015-10-29
相关资源
最近更新 更多