کیان
2 سال پیش توسط کیان مطرح شد
23 پاسخ

مشکل در استفاده همزمان از withCount و cursorPaginate در لاراول

سلام به همه دوستان و اساتید عزیز
من در استفاده همزمان از withCount و orderBy و cursorPaginate به مشکل خوردم
در واقع میخوام لیست پروفایل هام رو برگردونم ولی بر اساس تعداد فالورهاشون از زیاد به کم پس کوئری ام رو اینطوری نوشتم

        $profile = Profile::with('user:id,photo')
            ->withCount('followers')
            ->where('verify', '=', 1)
            ->orderBy('followers_count', 'desc')
            ->cursorPaginate(20);

اما متاسفانه خطای زیر رو میده :

Column not found: 1054 Unknown column 'followers_count' in 'where clause'

خب امتحان کردم 20 تای اول رو برمیگردونه اما وقتی cursor درست میشه و میخوام 20 تای بعد رو برگردونم خطای بالا رو میده و انگار ستون followers_count رو پیدا نمیکنه

جالب اینکه از paginate استفاده میکنم کار میکنه اما وقتی از cursorPaginate استفاده میکنم این خطا رو میده
دلیل استفاده از cursor هم که دیگه فکر کنم مشخص هست و نیاز به توضیح نیست

ممنون میشم اگر بشه راهنمایی کنید هر چی سرچ کردم به نتیجه نرسیدم
سپاس


ثبت پرسش جدید
کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
1

با کمی تاخیر خواستم راه حل مشکل بوجود اومده رو اینجا بنویسم شاید بعدا به کار کسی بیاد
از اونجایی که پس از پرسش و پاسخ های زیاد به نتیجه خاصی نرسیدم با لینکی که دوستمون معرفی کرد البته راهکاری برای این موضوع به صورت مستقیم نداشت اما در کل ممنونم چون با استفاده ازش یه ایده به ذهنم رسید
برای حل این مشکل اگر بشه دیتابیس رو به نوعی به فرض (( فریز )) کنیم که در واقع بگیم تا این time داده ها رو برای من کش کن مشکل در واقع حل میشد پس :

  if ($request->time != null){
            $time = $request->time;
            $profile = Profile::withCount(['followers' => function ($query) use ($time) {
                    $query->where('created_at', '<', $time);
                }])
                ->orderBy('followers_count', 'desc')
                ->orderBy('id', 'ASC')
                ->paginate(20);
        } else {
            $time = Carbon::now()->toDateTimeString();
            $profile = Profile::withCount('followers')
                ->orderBy('followers_count', 'desc')
                ->orderBy('id', 'ASC')
                ->paginate(20);
        }

طبق این کد بار اول همزمان با گرفتن داده ها time رو هم کش میکنیم و میگیم که تا این time من داده ها رو کش کردم و برای page های بعد اون time گرفته شده رو هم ارسال میکنیم و یه شرط اضافه میکنیم که داده هایی رو میخوایم که قبل از این time باشه
اینطوری کوچکترین اتفاقاتی هم اگر توی دیتابیس بیفته چه اضافه شدن رکورد چه کم شدن و ... دیگه لحاظ نمیشه و مشکل با همون paginate ساده هم حل میشه

در پایان از همه دوستانی که وقت گذاشتند و راهنمایی کردند ممنونم


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

سلام
من از withCount و coursorPagination استفاده نکردم که بتونم راهنمایی کنم مشکلتون رو
اما معمولا count و sum نیاز به groupBy دارند که بر اون اساس دسته بندی بشن.

ولی اگر در پایان مشکل چیزی بود که روش اشتباهی بود مثلا یا هر چیزی پیشنهاد من استفاده از

->select(DB::raw('count(profile.flowers) as flower_count'))

به جای اون with هست و بقیه مواردی که نیاز هست مثلا products.* رو میتونی در کنار این count اضاف کنی و استفاده کنی

من کد هام چون join داره خیلی هاش و همچین توابع محاسباتی مثل sum و count نیازم میشه از روشی که مثال زدم استفاده میکنم.


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش آپدیت شد
0

سلام مجدد
آقا من 2 روزه درگیر این مورد هستم هر کار میکنم جور در نمیاد حتی برای پیج اول یعنی 20 تای اول از این طریق :

DB::enableQueryLog();
کد ها 
dd(DB::getQueryLog());

کوئری رو چک میکنم با کوئری پیج دوم یعنی 20 تای دوم دقیقا شبیه هم هستند اما 20 تای اول برمیگرده توی 20 تای دوم این خطا رو میده :

Column not found: 1054 Unknown column 'followers_count' in 'where clause'

نمیدونم چکار باید کرد
عجیب تر اینکه با paginate کار میکنه مشکلش با cursorPaginate هست
اون موردی که دوست عزیزمون @salar.mohammad2013 گفتند بررسی کردم کلا نتونستم اجراش کنم هر بار به شکل های مختلف اما کلا نتونستم خروجی بگیرم
ممنون میشم راهنمایی کنید سپاس

@samanzdev
@mhyeganeh
@mohammadphp
@endworld
@hosseinshirinegad98
@alarus7
@abdolrahman
@salar.mohammad2013
@spaceman


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

جدول user و profile رو لطفا بزار برامون


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

کد زیر رو لطفا خروجی بگیر ببین چی نمایش میده.

        $profiles=Profile::join('users','users.id','profiles.user_id')
            ->select(DB::raw('users.id,users.photo,profiles.*,count(profiles.flowers) as flowerCount'))
            ->groupBy('profiles.id')
            ->paginate(10);

کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
0

@salar.mohammad2013 عزیز ممنون
ببینید توی کوئری اون with اول که یوزر هست رو نادیده بگیرید چون اون رو هم برداریم مشکل همچنان پابرجاست (در واقع اون برای برگردوندن عکس یوزر هست برای نماش توی اندروید) در واقع رابطه جدول profiles با profile_followers مدنظر هست بنابراین ->
شمای جدول profiles :

        Schema::create('profiles', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('user_id')->unsigned()->index()->unique();
            $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
            $table->bigInteger('city_id')->unsigned()->index();
            $table->foreign('city_id')->references('id')->on('cities');
            $table->string('title');
            $table->boolean('verify')->default(false);
            $table->softDeletes();
            $table->timestamps();
        });

شمای جدول profile_followers :

        Schema::create('profile_followers', function (Blueprint $table) {
            $table->id();
            $table->bigInteger('profile_id')->unsigned();
            $table->foreign('profile_id')->references('id')->on('profiles')->onDelete('cascade');
            $table->bigInteger('follower_id')->unsigned();
            $table->foreign('follower_id')->references('id')->on('users')->onDelete('cascade');
            $table->unique(['profile_id','follower_id']);
        });

و رابطه مربوطه توی مدل profile :

    public function followers()
    {
        return $this->hasMany(ProfileFollower::class);
    }

من با postman که ران میگیرم توی 20 تای اول هیچ مشکلی ندارم وقتی 20 تای اول برمیگرده توی حالت cursorPaginate یه استرینگ داریم به نام next_page_url که 20 تای بعدی رو برمیگردونه وقتی از اون میخوام استفاده کنم خطای میده که نمیتونه ستونی به نام followers_count پیدا کنه در صورتیکه با همین ستون توی 20 تای اول orderBy رو انجام داده حالا دقیقا چه اتفاقی میفته این وسط واقعا گیج شدم


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

اها یه موضوعی هم که الان به فکرم رسید اینه که شما اومدی بر اساس followers_count مرتب سازی کردی خروجی رو و orderBy قرار دادی
flowerCount یک فیلد محاسباتیه و روش به این شکل تا جایی که من تلاش کردم قبلا نمیشه کار کرد
معمولا برای این ها از having استفاده میشه که اونم برای بزرگ تر یا کوچک تری هست نسبت به یک مقدار خاص
شما روی orderBy تحقیق کن که چطور میتونی استفاده کنی روی همچین فیلد محاسباتی


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

من فک کردم profile_followers فیلدی در جدول profile هست
کد زیر رو اجرا کنید.

        $profiles=Profile::join('users','users.id','profiles.user_id')
            ->join('profile_followers','profile_followers.profile_id','profiles.id')
            ->select(DB::raw('users.id,users.photo,profiles.*,count(profile_followers.id) as flowerCount'))
            ->groupBy('profiles.id')
            ->paginate(10);

کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
0

@salar.mohammad2013
این خطا رو میگیرم ... این چرا به profiles.user_id داره گیر میده منظورش اینه که اون رو هم groupBy کنیم ؟

 Syntax error or access violation: 1055 'mydatabase.profiles.user_id' isn't in GROUP BY (SQL: select count(*) as aggregate from (select users.id,users.photo,profiles.*,count(profile_followers.id) as followerCount from `profiles` inner join `users` on `users`.`id` = `profiles`.`user_id` inner join `profile_followers` on `profile_followers`.`profile_id` = `profiles`.`id` group by `profiles`.`id`) as `aggregate_table`)"

محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

شما این رو تست کنید ببینید جواب میده آیا

$profiles=Profile::join('users','users.id','profiles.user_id')
            ->join('profile_followers','profile_followers.profile_id','profiles.id')
            ->select(DB::raw('users.id,users.photo,profiles.*,count(profile_followers.id) as flowerCount'))
            ->groupBy('profiles.user_id')
            ->paginate(10);

کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
0

@salar.mohammad2013
انجام دادم وقتی profiles.user_id رو در واقع groupBy میکنم بعدش یکی یکی به تک تک ستون های دیگه جدول profiles گیر میده که اون هم isn't in GROUP BY هر دفعه هر کدوم رو اضافه کنم به groupBy به بعدی گیر میده
چرا واقعا ؟؟؟؟


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

نگران نباش
طبق لینک زیر فقط strict توی پوشه config>database رو برابر false قرار بده و همون profiles.id که اول فرستادم رو بزار توی groupBy

Edit your applications's database config file config/database.php
In mysql array, set strict => false to disable MySQL's strict mode


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
0

@salar.mohammad2013
اتفاقا همین لحظه داشتم راجع به همین سرچ میکردم و پیداش کرده بودم و false کردم اوکی شد فقط سوتی که داده بودم از join استفاده کرده بودم که باید در واقع برای اینکه همه پروفایل ها برگرده در کنارش تعداد فالوور ها از leftJoin استفاده بشه نه اینکه فقط پروفایل هایی که فالوور دارن
خروجی شد این :

        $profile = Profile::leftJoin('profile_followers', 'profile_followers.profile_id', 'profiles.id')
            ->select(DB::raw('profiles.*,count(profile_followers.profile_id) as followerCount'))
            ->groupBy('profiles.id')
            ->orderBy('followerCount','DESC')
            ->paginate(20);

خب تا اینجا مشکل حله یعنی این کوئری با paginate داره کار میکنه خب من نیاز به cursorPaginate دارم اون رو جایگزین کردم دوباره خطا دارم
یعنی در واقع برگشتم سر خونه اول زمانیکه با withCount کار میکردم و با paginate کار میکرد ولی با cursorPaginate کار نمیکرد
خطا :

Column not found: 1054 Unknown column 'profiles.*,count(profile_followers.profile_id)' in 'where clause'

دقیقا مشابه سری قبل 20 تای اول برمیگرده 20 تای دوم به بعد این خطا میاد

جناب @salar.mohammad2013 عزیز من یه پوزش هم به شما بدهکارم چون خیلی ممنونم که اینقدر وقت میگذارید و لطف میکنید و راهنمایی میکنید
سپاسگزارم


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

نه اقا خواهش وظیفست
همه اینجا در حد توانشون مشکلات بقیه رو راهنمایی میکنن و بقیه هم مشکلات خودشون رو
من همون ابتدای کار هم خدمتتون گفتم با cursorPaginate اشنایی ندارم و حالت دیگه ای از کدتون رو گفتم شاید ب کارتون بیاد که نیومد متاسفانه
اما جدای اون شما orderBy تون هم مشکل خواهد داشت ب نظرم
ان شاالله دوستان راهنمایی بفرمایند مشکلتون حل بشه.


حسین شیری نژاد
تخصص : programmer
@hosseinshirinegad98 2 سال پیش مطرح شد
0

سلام مهندس به مستندات لاراول مربوط به این موضوع سری بزنید


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
0

@hosseinshirinegad98 مهندس جان توی laravel documention مراجعه کردم چیزی در این مورد اشاره نکرده
توی stackoverflow هم نگاه کردم همه فقط با paginate پیشنهاد داده بودند و کسی cursorPaginate رو نگفته بود
paginate هم که مشکلات خودش رو داره
حتی توی stackoverflow سوال پرسیدم هنوز کسی جواب نداده
موندم واقعا این قضیه نباید اینقدر پیچیده باشه خب همین الان هم جاهای مختلف داره استفاده میشه این قضیه
ممنون میشم اگر کسی راه حلی داره کمک کنه
سپاس


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش آپدیت شد
0

و من که همچنان درگیر این داستان هستم !!!! 🤔🤔🤔
آقا یه سوالی طبق مستندات خود لاراول که این هست :

# Cursor Pagination...
select * from users where id > 15 order by id asc limit 15;

cursorPaginate در واقع برای زمانی هست که میخوایم orderBy رو بر اساس id بگذاریم و توی حالت های دیگه کاربرد نداره ؟؟؟!!!! درسته؟

و اینکه من همچنان با count مشکل دارم
یه سوال توی فروشگاه هایی مثل دیجی و ... که دسته بندی هایی مثل پرفروش ترین ها و پربازدیدترین و ... دارندچطوری عمل میکنند ؟؟؟


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
0

آقا ممنون میشم اگر کسی از اساتید میتونه کمک کنه من هر راهی رفتن نشد کوئری خام زدم نشد هر دری زدم باز نشد
لطفا اگر تجربه ای دارید راهنمایی کنید تشکر
0
@samanzdev
@mhyeganeh
@mohammadphp
@endworld
@hosseinshirinegad98
@alarus7
@abdolrahman
@salar.mohammad2013
@spaceman
@ali.bayat
@hesammousavi
@Alimotreb
@juza66
@mohsenbostan
@mohaligateway
@Rp76
@abdolrahman
@ajdar9667
@ali.farmani
@hekmati
@mimsadAlef
@TimeRunner2359
@mohammadphp
@rezajahangir


محمد رضا
تخصص : Full Stack Developer
@salar.mohammad2013 2 سال پیش مطرح شد
0

سلام مجدد
در رابطه با بخش دوم سوالتون که بازدید و فروش هست
فقط کافیه فیلدی قرار بدید توی جدول و با هر بازدید یا فروش با لاراول دستور increment رو اجرا کنید.
دلیلی که میگم فیلد قرار داده بشه این هست که شما میخوایید sort کنید و من روی فیلد محاسباتی نتونستن sort انجام بدم .
مگر اینکه کل داده ها روبگیری count داشته باشی و بعد بیایی sort کنی که نمیشه همچین چیزی داده ها زیاد هستند.

در رابطه با cursorPagination هم لطفا کامل توضیح بدید میخوایید چیکار کنید و به چی برسید که بشه راهنمایی کرد با روش هایی .


کیان
تخصص : ندارم ...
@kian.myphone 2 سال پیش مطرح شد
0

لطفا به این عکس نگاه کنید :
https://use-the-index-luke.com/static/offset-drifting.Q318xIG4.png

این عکس دقیقا علت استفاده از cursorPaginate رو نشون میده
به طور خلاصه تصور کنید توی برنامه هایی که تعداد داده های زیاد هست شما وقتی با paginate ساده تعدادی از رکوردها رو مثلا 20 تای اول رو کش میکنید و نمایش میدید وقتی کاربر میخواد وارد پیچ دوم بشه قاعدتا باید 20 تای دوم رو ببینه اما اگر توی فاصله زمانی داده جدیدی اضافه بشه یا اینکه حذف بشه چه اتفاقی میفته وقتی میخوایم تعداد 20 تای دوم رو کش کنیم با توجه به آخرین وضعیت دیتابیس این اتفاق میفته و اینطوری یا رکوردهایی رو تکراری میبینیم یا بعضی از رکوردها اصلا کش نمیشن و علتش توی تصویر کاملا مشهوده
بنابراین باید از cursorPaginate استفاده کنیم که در واقع این مشکل رو حل کرده
من خودم این به این مشکل برخوردم که توی یه سوال دیگه پرسیدم و یکی از دوستان عزیز این مورد رو راهنمایی کردند و مشکل حل شد این لینک همون سوال هست :
https://roocket.ir/discuss/%D8%A2%D9%82%D8%A7-%DA%AF%DB%8C%D8%AC-%D8%B4%D8%AF%DB%8C%D9%85-%D8%B1%D9%81%D8%AA-%D9%85%D8%B4%DA%A9%D9%84-%D8%A8%D8%A7-paginate-%D9%88-%D9%87%D9%86%D8%AF%D9%84-%D8%A2%D9%86-%D8%B3%D9%85%D8%AA-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF

حالا هم داستان من اینطوری هست که وقتی من بخوام بر اساس id بیام orderBy رو انجام بدم مشکلی نیست اما وقتی میخوام بر اساس روابط بین مدل ها count رو صدا بزنم و بر اساس اون orderBy کنم به مشکل برمیخورم و مشکل رو بالاتر کامل توضیح دادم یعنی با paginate ساده مشکلی ندارم اما با cursorPaginate میتونم 20 تای اول رو صدا بزنم ولی بعدش خطا میده مه ستونی به اسم follower_count وجود نداره که بخوام اون رو شرط بگذارم برای ادامه کار
....


برای ارسال پاسخ لازم است وارد شده یا ثبت‌نام کنید

ورود یا ثبت‌نام