Laravel-Как объединить две коллекции, когда один столбец является общим в обеих коллекциях? - PullRequest
0 голосов
/ 25 сентября 2018

Я использую Laravel 5.6.38.

У меня есть две коллекции.

Коллекция 1

[{
"link": "http://example.com/videos/1",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 1",
"video_id": 1,
"priority": "2",
"identifiedBy": "x",

},
{
"link": "http://example.com/videos/2",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 2",
"video_id": 2,
"priority": "3",
"identifiedBy": "x",
}]

Коллекция 2

[{
"video_id": 1,
"qatagger": "Mr. X"
}]

Ожидаемый результат

[{
"link": "http://example.com/videos/1",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 1",
"video_id": 1,
"priority": "2",
"identifiedBy": "x",
"qatagger": "Mr. X"
},
{
"link": "http://example.com/videos/2",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 2",
"video_id": 2,
"priority": "3",
"identifiedBy": "x",
}]

Я пробовал $ collection1-> merge ($ collection2), получаю результат

[{
"link": "http://example.com/videos/1",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 1",
"video_id": 1,
"priority": "2",
"identifiedBy": "superadmin"
},
{
"link": "http://example.com/videos/2",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 2",
"video_id": 2,
"priority": "3",
"identifiedBy": "superadmin"
},
{
"video_id": 1,
"qatagger": "Mr. x"
}]

Могу ли я в любом случае получить ожидаемый результат, используя любой цикл?

Обновление 1-е объединение

$videos = DB::table('videos')
            ->where('videos.video_status_id', '=', $status)
            ->leftJoin(DB::raw("(SELECT video_id, comment, comment_type FROM comments WHERE comment_id in (SELECT MAX(comment_id) FROM comments
    GROUP BY comment_type, video_id ASC) AND comment_type = 'vip_comment') comments_vip"), 'videos.video_id', '=', 'comments_vip.video_id')
            ->leftJoin(DB::raw("(SELECT video_id, comment, comment_type FROM comments WHERE comment_id in (SELECT MAX(comment_id) FROM comments
    GROUP BY comment_type, video_id ASC) AND comment_type = 'pm_comment') comments_pm"), 'videos.video_id', '=', 'comments_pm.video_id')
            ->leftJoin(DB::raw("(SELECT video_id, comment, comment_type FROM comments WHERE comment_id in (SELECT MAX(comment_id) FROM comments GROUP BY comment_type, video_id ASC) AND comment_type = 'tagging_qa_comment') comments_tq"),'videos.video_id', '=', 'comments_tq.video_id')
            ->leftJoin('users AS identifiedByUser', function($join) {
                $join->on('videos.video_identified_by', '=', 'identifiedByUser.id');
            })
            ->select(['videos.video_id as video_id', 'videos.video_link as link', 'videos.video_status_id as status_id', 'videos.video_description as description', 'videos.video_priority as priority', 'videos.created_at as created_at', 'comments_vip.comment AS vip_comment', 'comments_pm.comment AS 
            pm_comment', 'comments_tq.comment as tagger_qa_comment', 'identifiedByUser.name as identifiedBy'])
            ->groupBy('video_id')
            ->get();

2-е соединение

$taggers = DB::table('video_taggings')
                    ->leftJoin('videos', 'video_taggings.video_id', '=', 'videos.video_id' )
                    ->join('users AS taggers', function($join) {
                        $join->on('video_taggings.tagging_team_id', '=', 'taggers.id');
                    })->select(array('videos.video_id as video_id', 'taggers.name as tagger'))
                    ->get()->keyBy('video_id'); 

Слияние

$out = [];
    foreach ($videos as $key => $video){
        $video->priority = Priority::where('priority_id', '=', $video->priority)->pluck('display_name')->first();
        $video = new Collection($video);
        $out[] = $video->merge($taggers[$video['video_id']]);
    }

Ответы [ 3 ]

0 голосов
/ 26 сентября 2018

Обходной путь будет

$out = array();
 foreach ($collections1 as $key => $collection1){
      $out[] = (object)array_merge((array)$collections2[$key], (array)$value);
 }

dd(new \Illuminate\Support\Collection($out));

Лучшим подходом (пока рабочим решением) может быть

$out = [];
    foreach ($videos as $key => $video){
        $video->priority = Priority::where('priority_id', '=', $video->priority)->pluck('display_name')->first();
        $video = new Collection($video);
        $out[] = $video->merge($taggers[$video['video_id']]);
    }

    return new Collection($out);

снова обходной путь.

0 голосов
/ 27 сентября 2018

Как я предлагал в моих комментариях, вы можете добавить таблицу как дополнительное объединение в запросе, чтобы получить результаты из базы данных.Вероятно, сработает что-то похожее на приведенное ниже:

 $videos = DB::table('videos')
        ->where('videos.video_status_id', '=', $status)
        ->leftJoin(DB::raw("(SELECT video_id, comment, comment_type FROM comments WHERE comment_id in (SELECT MAX(comment_id) FROM comments
GROUP BY comment_type, video_id ASC) AND comment_type = 'vip_comment') comments_vip"), 'videos.video_id', '=', 'comments_vip.video_id')
        ->leftJoin(DB::raw("(SELECT video_id, comment, comment_type FROM comments WHERE comment_id in (SELECT MAX(comment_id) FROM comments
GROUP BY comment_type, video_id ASC) AND comment_type = 'pm_comment') comments_pm"), 'videos.video_id', '=', 'comments_pm.video_id')
        ->leftJoin(DB::raw("(SELECT video_id, comment, comment_type FROM comments WHERE comment_id in (SELECT MAX(comment_id) FROM comments GROUP BY comment_type, video_id ASC) AND comment_type = 'tagging_qa_comment') comments_tq"),'videos.video_id', '=', 'comments_tq.video_id')
        ->leftJoin('users AS identifiedByUser', function($join) {
            $join->on('videos.video_identified_by', '=', 'identifiedByUser.id');
        })
        ->select(['videos.video_id as video_id', 'videos.video_link as link', 'videos.video_status_id as status_id', 'videos.video_description as description', 'videos.video_priority as priority', 'videos.created_at as created_at', 'comments_vip.comment AS vip_comment', 'comments_pm.comment AS 
        pm_comment', 'comments_tq.comment as tagger_qa_comment', 'identifiedByUser.name as identifiedBy', 'joinedTable.tagger as tagger'])
        ->leftJoin(DB::raw('('.
                DB::table('video_taggings')
                    ->leftJoin('videos', 'video_taggings.video_id', '=', 'videos.video_id' )
                    ->join('users AS taggers', function($join) {
                        $join->on('video_taggings.tagging_team_id', '=', 'taggers.id');
                    })->select(array('videos.video_id as video_id', 'taggers.name as tagger'))->toSql()
            .') as joinedTable'), 'joinedTable.video_id', 'videos.video_id')
        ->groupBy('video_id')
        ->get();

Это использование метода toSql, который сохранит точный запрос, который вы выполняете для своего второго случая.Я фактически не проверял это как бы то ни было.

Обходной путь с использованием полученных коллекций:

$result1->map(function ($row) use ($result2) {
      if ($result2->has($row->video_id)) {
         return collect(array_merge((array)$row, (array)$result2)); //Casting to arrays and then to a collection. 
      }
      return collect((array)$row);
});
0 голосов
/ 25 сентября 2018

Вы не можете объединиться после выхода из результата, вы должны объединить свой запрос. На каком основании вы будете включены в этот результат, здесь нет никаких требований.

Это решение, но я не вижу этогоправда

$arr1 = json_decode('[{
"link": "http://example.com/videos/1",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 1",
"video_id": 1,
"priority": "2",
"identifiedBy": "x"
},
{
"link": "http://example.com/videos/2",
"created_at": "2018-09-20 05:14:10",
"description": "some desc 2",
"video_id": 2,
"priority": "3",
"identifiedBy": "x"
}]');

$arr2 = json_decode('[{
"video_id": 1,
"qatagger": "Mr. X"
}]');

$arr1[0] = (object)array_merge((array)$arr1[0],(array)$arr2[0]);
dd(new \Illuminate\Support\Collection($arr1));
...