雄辩的 ORM 交叉搜索

Posted

技术标签:

【中文标题】雄辩的 ORM 交叉搜索【英文标题】:Eloquent ORM cross search 【发布时间】:2017-10-05 11:21:07 【问题描述】:

我正在构建一个小型搜索引擎来获取世界各地的多个旅程,这是我的旅程表的样子:

如您所见,department_checkpoint 和arrival_checkpoint 是链接在一起的,这是一个完整的旅程,所有这些目的地都属于同一个announce_id 2。我现在要做的是创建一个表格,您可以在其中插入您的出发点和到达点以及搜索引擎将返回包含这些目的地的announce_id。获取像巴黎到伦敦或维也纳到多伦多这样的并排位置很简单,但是如何进行交叉搜索以获取像巴黎 - 维也纳或巴黎 - 多伦多这样的旅程? (穿越目的地)。

我正在使用 Eloquent ORM,这就是我目前所拥有的:

public function search(Request $request) 

    if ($request->isMethod('post')) 

        $departure = $request->get('departure');
        $arrival = $request->get('arrival');

        $announceIds = DB::table('journeys')
            ->select(DB::raw('announce_id'))
            ->where('departure_checkpoint', $departure)
            ->where('arrival_checkpoint', $arrival)
            ->get();

        foreach($announceIds as $value) 

            $this->founds = DB::table('announcesForDelivery')
                ->select(DB::raw('*'))
                ->where('announce_id', $value->announce_id)
                ->get();
        

        return response()->json($this->founds);
    

    return false;

这仅适用于并排搜索,但不适用于交叉搜索。我想我将不得不使用announce_id 来获取任何旅程,但我不确定如何使用Eloquent ORM 来做到这一点,它会是一个子查询吗?

【问题讨论】:

【参考方案1】:

这是您可以使用的(不是最好的)解决方案之一:

程序:

查找具有给定出发检查站的旅程 使用给定的到达检查点和给定的从出发的announce_ids 查找旅程查找结果 检查确定的出发 ID 是否小于或等于确定的到达 ID(否则反向出发与到达仍然有效)

$departure = '巴黎';

$departure = 'Paris';
$arrival = 'Vienne';

// First pick journeys with given departure
$journeysWithDeparture = DB::table('journeys')
    ->where('departure_checkpoint', $departure)
    ->get();

// Then pick only journeys which has given arrival
$journeysWithArrival = DB::table('journeys')
    ->whereIn('announce_id', $journeysWithDeparture->pluck('announce_id')->toArray())
    ->where('arrival_checkpoint', $arrival)
    ->get();


$foundedAnnounceIds = [];
$processedAnnounceIds = [];

// Pick only journeys where departureId <= arrivalId
foreach ($journeysWithArrival as $journey)

    if(in_array($journey->announce_id, $processedAnnounceIds))
    
        continue;
    

    $departure = $journeysWithDeparture->whereStrict('announce_id', $journey->announce_id)->first();

    if (isset($departure) && $journey->id >= $departure->id)
    
        $foundedAnnounceIds[] = $journey->announce_id;
    

    $processedAnnounceIds[] = $journey->announce_id;


dd($foundedAnnounceIds);

【讨论】:

感谢您的回答,看起来它可以做到这一点,我尝试过并让您知道。 我验证了你的答案,它现在就像一个魅力!谢谢。【参考方案2】:

嗯……早上喝咖啡和 SQL……哈哈

这样的事情怎么样:

select id_a from 
    (select announce_id id_a from Journeys where departure_checkpoint = 'paris') a
inner join
    (select announce_id id_b from Journeys where arrival_checkpoint = 'london') b
on a.id_a = b.id_b;

因此,您将获得出发地所在的所有公告 ID,将其与目的地所在的所有公告 ID 内联起来...将返回这两个用户输入的城市所在的所有旅程的列表...

这是你想要做的吗?

【讨论】:

以上是关于雄辩的 ORM 交叉搜索的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM 交叉产品

使用Python ORM的交叉表(列联表)?

交叉表左连接,Django ORM

我是不是需要同时执行网格搜索(使用交叉验证)和交叉验证方法?

交叉验证和网格搜索有啥区别?

机器学习交叉验证和网格搜索