laravel eloquent 子查询相同 table 不同列

laravel eloquent subquery same table different columns

我正在尝试在 laravel eloquent 中重新构造一个有效的 mysql 查询(或具有相同结果的更好的查询)。我的数据库看起来像这样:

我有一个 words table 列 idname。 我有一个名为 synonyms 的枢轴 table,其中包含 idword_id 列和 synonym_id.

同义词 table 将同义词链接在一起。例如,它将自行车和自行车连接在一起。但也骑自行车等

我确实在我的 phpstorm 编辑器中构建了这个查询并且它有效:

select * from words
where id in (
    select synonym_id from synonyms
    where word_id in (select id from words where name = 'bike')
)
or id in (
    select word_id from synonyms
    where synonym_id in (select id from words where name = 'bike')
)

它returns一个结果集,包含自行车、串联、自行车等

我确实创建了一个具有这些方法的“单词”eloquent模型:

 /**
 * Synonyms for this word
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 */
public function synonyms() {
    return $this->belongsToMany(Word::class, 'synonyms', 'synonym_id', 'word_id');
}

/**
 * Words that have this word as their synonym
 *
 * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
 */
public function isSynonymFor() {
    return $this->belongsToMany(Word::class, 'synonyms', 'word_id', 'synonym_id');
}

现在我正在尝试在 eloquent 中重建该查询,如下所示:

    $word = 'bike'; //Just for debugging purposes I hardcoded it.
    $query = Word::whereHas('isSynonymFor', function(Builder $query) use($word) {
        $query->where('name', '=', $word);
    })->orWhereHas('synonyms', function(Builder $query) use($word) {
        $query->where('name', '=', $word);
    })

    return $query->get();

这并不像我想要的那样有效。它只是 returns 一个包含“自行车”而不是其他内容的集合。

我该如何解决?

如果你只想重现那个确切的查询(没有使用 eloquent 关系),你应该能够用 whereIn(column, Closure) 来做子查询。

$query = DB::table('words') 
    ->whereIn('id', function ($sub) {
        $sub->select('synonym_id')
            ->from('synonyms')
            ->whereIn('word_id', function ($sub2) {
                $sub2->select('id')
                     ->from('words')
                     ->where('name', 'bike');
            });
    })
    ->orWhereIn('id', function ($sub) {
        $sub->select('word_id')
            ->from('synonyms')
            ->whereIn('synonym_id', function ($sub2) {
                $sub2->select('id')
                     ->from('words')
                     ->where('name', 'bike');
            });
    })
    // ->toSql();
    ->get();