成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

laravel較優(yōu)雅的分表關(guān)聯(lián)查詢(性能較好,SQL的數(shù)量=表的數(shù)量,涵蓋了較多l(xiāng)aravel手冊(cè)推

mylxsw / 3648人閱讀

摘要:最優(yōu)就只能是查詢表的數(shù)量才算是比較合理,完全有足夠的能力寫出優(yōu)雅的代碼很多人可能會(huì)想到的原生查詢了么。但是有強(qiáng)大的關(guān)聯(lián),訪問器修改,查詢范圍等等這些功能讓你的代碼非常簡(jiǎn)潔。相信熟悉的人已經(jīng)知道怎么查詢了,可以達(dá)到最優(yōu)化的,和最優(yōu)雅的寫法。

終于被產(chǎn)品的各種刁鉆不合常理的需求磨煉出用laravel寫出較為優(yōu)雅的代碼,在這里給大家分享一下。

先簡(jiǎn)單介紹一下基本環(huán)境,我們是做一款直播APP的,人很多,所以每個(gè)接口都必須盡量?jī)?yōu)化(主要是SQL的查詢)。

有一天,產(chǎn)品跟我們說(shuō),那個(gè)針對(duì)主播的送禮牌行榜能否顯示30天內(nèi)的用戶送禮數(shù)倒序排列,顯示用戶是否VIP,用戶對(duì)主播的親密度,還有用戶的等級(jí)。

30天內(nèi)的數(shù)據(jù)。也就是說(shuō)之前那張一直累計(jì)數(shù)值的排行表不能使用了,而且這個(gè)30天是個(gè)動(dòng)態(tài)的,也就是說(shuō)這個(gè)數(shù)據(jù)必須只能利用送禮流水group by出來(lái)。我們的送禮流水表是1個(gè)月1張表的

介紹一下基本表的情況
用戶表user
用戶資料表user_ext(你大爺?shù)念^像竟然放這張表,誰(shuí)搞的站出來(lái),看我不弄死你)
禮物表honey_log_201708(XXXX分表日期)
超級(jí)VIP表svip
親密度表qinmi
(這幾張表的關(guān)聯(lián)是無(wú)法避免的,加上分頁(yè)count查詢。SQL最優(yōu)就只能是查詢表的數(shù)量+1才算是比較合理,laravel完全有足夠的能力寫出優(yōu)雅的代碼)

很多人可能會(huì)想到laravel的DB原生查詢了么。但是Eloquent有強(qiáng)大的關(guān)聯(lián),訪問器修改,查詢范圍等等這些功能讓你的代碼非常簡(jiǎn)潔。

我們先寫model
1.用戶表user
關(guān)鍵字段是id用戶ID,nickanem昵稱,exp經(jīng)驗(yàn)值

exp, config("user.level.num"));
    }
}

2.用戶資料表
主要字段uid主鍵,header_name頭像文件名,header_lock頭像是否被鎖(0,1)

header_lock == 1 || $this->header_name == "") {
            $headerUrl = "http://www.cdn.com/" . "default_header_user.png";
        } else {
            $headerUrl = "http://www.cdn.com/" . $this->header_name;
        }
        return $headerUrl;
    }
}

3.SVIP表
主要字段uid主鍵,expire過期時(shí)間

where("expire", ">", LARAVEL_START);
    }
}

4.親民度qinmi表
主要字段uid,beauty_uid(主播主鍵),qinmi_num親密度值

qinmi_num, config("qinmi.qinmi.num"));
    }
}

5.好了,重點(diǎn)來(lái)了。honey_log表,這個(gè)是重點(diǎn),因?yàn)樗欠直淼?,現(xiàn)在我們要封裝一個(gè)union表的方法,讓這個(gè)model自動(dòng)把涉及的分表作為一張表賦予model查詢

=", $startTime], ["time", "<", $endTime]], $wheres);
        //時(shí)間戳轉(zhuǎn)日期
        $startDate = date("Y-m", $startTime);
        $endDate = date("Y-m", $endTime);
        //涉及的表數(shù)組
        $tables = [];
        //循環(huán)where數(shù)組,格式是[["字段","表達(dá)式","值"," and|or "],["字段","表達(dá)式","值"," and|or "]]
        //例子[["beauty_uid", "=", "2011654", "and"]]
        foreach ($wheres as $val) {
            //組裝每個(gè)where條件
            $val[2] = $val[2] ? $val[2] : """";
            if (isset($val[3])) {
                $whereConditions[] = " {$val[3]} {$val[0]} {$val[1]} {$val[2]}";
            } else {
                $whereConditions[] = " and {$val[0]} {$val[1]} {$val[2]}";
            }
        }
        //循環(huán)開始日期和結(jié)束日期計(jì)算跨越的表
        for ($i = $startDate; $i <= $endDate; $i = date("Y-m", strtotime($i . "+1month"))) {
            $tables[] = "select " . implode(",", $attributes) . " from cdb_honey_log_" . date("Yn", strtotime($i)) . " where 1" . implode("", $whereConditions);
        }
        //會(huì)得到每一個(gè)表的子查詢,因?yàn)槎加屑s束條件,所以每一個(gè)子查詢得結(jié)果集都不會(huì)很多
        //用setTable的方法把這個(gè)子查詢union all 后 as一個(gè)表名作為model的table屬性
        //sql大概會(huì)是:(select xxx,xxx from honey_log_20177 where time >= 開始日期 and time < 結(jié)束日期 and xxx union all select xxx,xxx from honey_log_20178 where time >= 開始日期 and time < 結(jié)束日期 and xxx) as cdb_honey_log
        //核心是看你輸入的開始日期和結(jié)束日期和約束條件,組裝成一個(gè)union all的子查詢?nèi)缓笞鳛閠able賦予model
        return $this->setTable(DB::raw("(" . implode(" union all ", $tables) . ") as cdb_honey_log"));
    }

    //關(guān)聯(lián)用戶資料表,要拿頭像
    public function userExt()
    {
        return $this->belongsTo(UserExt::class, "uid");
    }
    //關(guān)聯(lián)用戶表,要拿昵稱
    public function user()
    {
        return $this->belongsTo(User::class, "uid");
    }
    //關(guān)聯(lián)SVIP表,要判斷是否VIP
    public function svip()
    {
        return $this->belongsTo(Svip::class, "uid");
    }
    //關(guān)聯(lián)用戶對(duì)于主播的親民值
    public function qinmi()
    {
        return $this->hasMany(Qinmi::class, "uid", "uid");
    }
    //轉(zhuǎn)化送禮等級(jí),按送禮金額轉(zhuǎn)化
    public function getHoneyLevelAttribute()
    {
        return section($this->honey_num, config("beauty.honey.num"));
    }
}

以上準(zhǔn)備工作都有了。相信熟悉laravel的人已經(jīng)知道怎么查詢了,可以達(dá)到最優(yōu)化的SQL,和最優(yōu)雅的laravel寫法。
好。我們來(lái)看看控制器如何查詢

input("beauty_uid");
        // 每頁(yè)顯示數(shù)量
        $pageSize = $request->input("pagesize", 10);
        // 當(dāng)前頁(yè)
        $page = $request->input("page");
        // 緩存數(shù)據(jù),按查詢的主播,頁(yè)數(shù)作為key分頁(yè)
        $data = Cache::remember("user_for_beauty_rank_{$beauty_uid}_{$pageSize}_{$page}", 2, function () use ($beauty_uid, $pageSize, $page) {
            // 計(jì)算30天前
            $startTime = Carbon::today()->subDays(30)->getTimestamp();
            // 計(jì)算結(jié)束日期
            $endTime = Carbon::tomorrow()->getTimestamp();
            // 實(shí)例化honeyLog模型,因?yàn)樽远x的setUnionAllTable方法是非靜態(tài)方法,如果誰(shuí)知道如何在model定義非靜態(tài)方法但是可以通過靜態(tài)調(diào)用的話,請(qǐng)告訴我,因?yàn)椴幌敫牡讓樱琹aravel是用了魔法靜態(tài)方法實(shí)例化調(diào)用的,所以我們才可以使用model::select()->where()->get()這樣的鏈?zhǔn)秸{(diào)用,但是在model自己定義的實(shí)體方法好像并沒有繼承到這種調(diào)用
            $honeyLog = new HoneyLog;
            // 查詢?cè)撝鞑D30天有親密值的用戶group by 排序 用分頁(yè)paginate
            $lists = $honeyLog->setUnionAllTable($startTime, $endTime, ["uid", "honey_num"], [["beauty_uid", "=", $beauty_uid]])
                ->select(DB::raw("uid, sum(honey_num) as honey_num"))->groupBy("uid")->orderBy("honey_num", "desc")->paginate($pageSize);
            // 很多人可能會(huì)問為什么不用with()渴求式加載,因?yàn)橛昧藈ith的話,model會(huì)默認(rèn)去構(gòu)造一次實(shí)例,導(dǎo)致table屬性丟失,你們?cè)囋嚲椭懒?,所以下面我們終于理解到laravel為什么會(huì)還有個(gè)懶惰渴求式加載了,簡(jiǎn)直絕配
            
            // 懶惰渴求式加載頭像,vip,親密值,昵稱
            // 好好理解下面的關(guān)聯(lián)約束
            $lists->load([
                "userExt" => function ($query) {
                    $query->select("uid", "header_name", "header_lock");
                },
                "user" => function ($query) {
                    $query->select("bid", "nickname", "exp");
                },
                "svip" => function ($query) {
                    // 這個(gè)validVip是模型定義的范圍約束方法,相當(dāng)于where("expire", ">", LARAVEL_START)
                    $query->select("uid")->validVip();
                },
                "qinmi" => function ($query) use ($beauty_uid) {
                    // 這里需要傳入主播ID,只查找用戶對(duì)于這個(gè)主播的親密值
                    $query->select("uid", "qinmi_num")->where("beauty_uid", $beauty_uid);
                }
            ]);

            // 現(xiàn)在需要的數(shù)據(jù)都已經(jīng)全部查出來(lái)了,由于我做的是API,現(xiàn)在要組裝前端需要的格式return出去就可以了,
            // 如果是自己做的web網(wǎng)頁(yè),就直接丟給視圖遍歷就可以了

            $result = [];
            foreach ($lists as $key => $value) {
                $result[] = [
                    // 用戶id
                    "uid" => $value->uid,
                    // 送禮數(shù)量
                    "honey_num" => $value->honey_num,
                    // 頭像
                    "header" => $value->userExt->header_url,
                    // 是否vip
                    "svip" => $value->svip ? 1 : 0,
                    // 送禮等級(jí)
                    "honey_level" => $value->honeyLevel,
                    // 親密等級(jí)
                    "qinmi_level" => $value->qinmi->isEmpty() ? 0 : $value->qinmi[0]->level,
                    // 昵稱
                    "nickname" => $value->user->nickname,
                    // 用戶等級(jí)
                    "level" => $value->user->level,
                ];
            }

            // 這是前端要求的格式,要這樣組裝沒有什么特別要說(shuō)的,只是前端習(xí)慣這樣的結(jié)構(gòu)
            $data = [
                "page" => [
                    "last_page" => $lists->lastPage(),
                    "current_page" => $lists->currentPage(),
                    "list" => $result,
                ],
            ];

            return $data;
        });
        
        return response()->json($data);
    }

}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/25615.html

相關(guān)文章

  • 首發(fā),laravel優(yōu)雅分表、關(guān)聯(lián)、分頁(yè)查詢,手冊(cè)方法熟練運(yùn)用。

    摘要:前幾天寫了一遍關(guān)于分表關(guān)聯(lián)的查詢,但是我個(gè)人覺得還不算完美,于是今天重新看了一下模型的底層代碼,終于寫出我暫時(shí)覺得最滿意的代碼風(fēng)格,簡(jiǎn)潔優(yōu)雅是核心。關(guān)聯(lián)查詢用了渴求式加載,就能有效減少的條數(shù),保證數(shù)據(jù)庫(kù)的性能。 前幾天寫了一遍關(guān)于laravel分表關(guān)聯(lián)的查詢,但是我個(gè)人覺得還不算完美,于是今天重新看了一下laravel模型的底層代碼,終于寫出我暫時(shí)覺得最滿意的代碼-laravel風(fēng)格,...

    fuchenxuan 評(píng)論0 收藏0
  • 美團(tuán)點(diǎn)評(píng)攜手 PingCAP 開啟新一代數(shù)據(jù)庫(kù)深度實(shí)踐之旅

    摘要:一背景和現(xiàn)狀在美團(tuán),基于構(gòu)建的傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)服務(wù)已經(jīng)難于支撐公司業(yè)務(wù)的爆發(fā)式增長(zhǎng),促使我們?nèi)ヌ剿鞲侠淼臄?shù)據(jù)存儲(chǔ)方案和實(shí)踐新的運(yùn)維方式。隨著近一兩年來(lái)分布式數(shù)據(jù)庫(kù)大放異彩,美團(tuán)團(tuán)隊(duì)聯(lián)合架構(gòu)存儲(chǔ)團(tuán)隊(duì),于年初啟動(dòng)了分布式數(shù)據(jù)庫(kù)項(xiàng)目。 一、背景和現(xiàn)狀 在美團(tuán),基于 MySQL 構(gòu)建的傳統(tǒng)關(guān)系型數(shù)據(jù)庫(kù)服務(wù)已經(jīng)難于支撐公司業(yè)務(wù)的爆發(fā)式增長(zhǎng),促使我們?nèi)ヌ剿鞲侠淼臄?shù)據(jù)存儲(chǔ)方案和實(shí)踐新的運(yùn)維方式。...

    gclove 評(píng)論0 收藏0
  • [靈魂拷問]MySQL面試高頻100問(工程師方向)

    摘要:黑客技術(shù)點(diǎn)擊右側(cè)關(guān)注,了解黑客的世界開發(fā)進(jìn)階點(diǎn)擊右側(cè)關(guān)注,掌握進(jìn)階之路開發(fā)點(diǎn)擊右側(cè)關(guān)注,探討技術(shù)話題作者丨呼延十排版丨團(tuán)長(zhǎng)前言本文主要受眾為開發(fā)人員所以不涉及到的服務(wù)部署等操作且內(nèi)容較多大家準(zhǔn)備好耐心和瓜子礦泉水前一陣系統(tǒng)的學(xué)習(xí)了一下也有 ...

    gyl_coder 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<