জ্যাঙ্গোতে একাধিক ফিল্টার () চাপানো, এটি কি বাগ?


107

আমি সর্বদা ধরে নিয়েছিলাম যে জ্যাঙ্গোতে একাধিক ফিল্টার () কল চেইন করা সর্বদা একক কলে তাদের সংগ্রহ করার মতো।

# Equivalent
Model.objects.filter(foo=1).filter(bar=2)
Model.objects.filter(foo=1,bar=2)

তবে আমি আমার কোডে একটি জটিল ক্যোয়ারসেট পেরিয়ে এসেছি যেখানে এটি ঘটনাটি নয়

class Inventory(models.Model):
    book = models.ForeignKey(Book)

class Profile(models.Model):
    user = models.OneToOneField(auth.models.User)
    vacation = models.BooleanField()
    country = models.CharField(max_length=30)

# Not Equivalent!
Book.objects.filter(inventory__user__profile__vacation=False).filter(inventory__user__profile__country='BR')
Book.objects.filter(inventory__user__profile__vacation=False, inventory__user__profile__country='BR')

উত্পাদিত এসকিউএল হ'ল

SELECT "library_book"."id", "library_book"."asin", "library_book"."added", "library_book"."updated" FROM "library_book" INNER JOIN "library_inventory" ON ("library_book"."id" = "library_inventory"."book_id") INNER JOIN "auth_user" ON ("library_inventory"."user_id" = "auth_user"."id") INNER JOIN "library_profile" ON ("auth_user"."id" = "library_profile"."user_id") INNER JOIN "library_inventory" T5 ON ("library_book"."id" = T5."book_id") INNER JOIN "auth_user" T6 ON (T5."user_id" = T6."id") INNER JOIN "library_profile" T7 ON (T6."id" = T7."user_id") WHERE ("library_profile"."vacation" = False  AND T7."country" = BR )
SELECT "library_book"."id", "library_book"."asin", "library_book"."added", "library_book"."updated" FROM "library_book" INNER JOIN "library_inventory" ON ("library_book"."id" = "library_inventory"."book_id") INNER JOIN "auth_user" ON ("library_inventory"."user_id" = "auth_user"."id") INNER JOIN "library_profile" ON ("auth_user"."id" = "library_profile"."user_id") WHERE ("library_profile"."vacation" = False  AND "library_profile"."country" = BR )

শৃঙ্খলাবদ্ধ filter()কলগুলির সাথে প্রথম ক্যোয়ারসেটটি দুটি মডেলের কার্যকরভাবে দুটি শর্তের মধ্যে একটি OR তৈরি করার জন্য ইনভেন্টরি মডেলে যোগ দেয় যেখানে দ্বিতীয় ক্যোয়ারসেট অ্যান্ডস দুটি শর্ত একসাথে করে। আমি আশা করছিলাম যে প্রথম ক্যোয়ারীটিও হবে এবং দুটি শর্তও। এটি কি প্রত্যাশিত আচরণ বা এটি জঙ্গোতে কোনও বাগ?

সম্পর্কিত প্রশ্নের উত্তর কি জাজানোতে ".filter ()। ফিল্টার ()। ফিল্টার () ..." ব্যবহার করার কোনও প্রতিকূলতা আছে? দুটি ক্যোয়ারেট সমান হওয়া উচিত বলে মনে হয়।

উত্তর:


121

আমি যেভাবে বুঝতে পারি তা হ'ল এগুলি ডিজাইনের মাধ্যমে সম্পূর্ণ ভিন্ন (এবং আমি অবশ্যই সংশোধনের জন্য উন্মুক্ত): filter(A, B)প্রথমে এ অনুযায়ী ফিল্টার করব এবং তারপরে বি অনুসারে সাবফিল্টার filter(A).filter(B)দেবে , এবং 'এবং' এর সাথে মিলিত একটি সারি ফিরে আসবে এবং 'সম্ভাব্য ভিন্ন' বি সাথে মেলে সারি

এখানে উদাহরণ দেখুন:

https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-mult- মূল্যবান- সম্পর্কিত সম্পর্ক

বিশেষত:

এই সমস্ত প্রয়োজনীয়তার সাথে মেলে এমন আইটেমগুলি ফিল্টার করার জন্য একক ফিল্টার () কলের অভ্যন্তরে থাকা সমস্ত কিছু একসাথে প্রয়োগ করা হয়। ধারাবাহিক ফিল্টার () কলগুলি অবজেক্টের সেটকে আরও সীমাবদ্ধ করে

...

এই দ্বিতীয় উদাহরণে (ফিল্টার (এ)। ফিল্টার (বি)), প্রথম ফিল্টার ক্যোরিসেটকে (এ) সীমাবদ্ধ করেছিল। দ্বিতীয় ফিল্টার ব্লগগুলির সেটটিকে আরও (বি) সীমাবদ্ধ করে। দ্বিতীয় ফিল্টার দ্বারা নির্বাচিত এন্ট্রিগুলি প্রথম ফিল্টারটিতে প্রবেশের মতো বা নাও থাকতে পারে `


18
এই আচরণটি নথিভুক্ত করা হলেও কমপক্ষে অবাক হওয়ার নীতি লঙ্ঘন করেছে বলে মনে হচ্ছে। একাধিক ফিল্টার () এর এবং একসাথে যখন ক্ষেত্রগুলি একই মডেলটিতে থাকে তবে সম্পর্কের ক্ষেত্রে যখন প্রশস্ত হয় তখন বা একসাথে।
জার্মডেম্ব

4
আমি বিশ্বাস করি এটি প্রথম অনুচ্ছেদে আপনার ভুল উপায়ে রয়েছে - ফিল্টার (এ, বি) হ'ল এ্যান্ড পরিস্থিতি (ডক্সে 'লেনন' এবং ২০০৮), ফিল্টার (এ)। ফিল্টার (বি) হল ওআর পরিস্থিতি ( 'লেনন' বা 2008)। আপনি যখন প্রশ্নটিতে উত্পন্ন উত্সগুলি দেখেন তখন এটি বোধগম্য হয় -। ফিল্টার (এ) .ফিল্টার (বি) কেসটি দু'বার যোগ দেয়, যার ফলে একটি ওআর হয়।
স্যাম

17
ফিল্টার (এ, বি) হল অ্যান্ড ফিল্টার (এ) f ফিল্টার (বি) হল OR
ওয়েজহংটু

4
তাই further restrictমানে less restrictive?
বোহ

7
এই উত্তরটি ভুল। এটি "OR" নয়। এই বাক্যটি "দ্বিতীয় ফিল্টার ব্লগগুলির সেটকে আরও (বি) এর মধ্যে সীমাবদ্ধ করে।" স্পষ্টভাবে "এটিও (বি)" উল্লেখ করেছে। আপনি যদি এই নির্দিষ্ট উদাহরণে ওআর এর অনুরূপ আচরণ পর্যবেক্ষণ করেন তবে এর অর্থ এই নয় যে আপনি নিজের ব্যাখ্যাটি সাধারণীকরণ করতে পারবেন। দয়া করে "কেভিন 3112" এবং "জনি স্যাং" এর উত্তরগুলি দেখুন। আমি বিশ্বাস করি সেগুলি সঠিক উত্তর।
ম্যান

71

এই দুটি শৈলীর ফিল্টারিং বেশিরভাগ ক্ষেত্রে সমান, তবে ফরেনকি বা ম্যান্টিটোম্যানিফিল্ডে অবজেক্ট বেসের বিষয়ে কোয়েরি করা হলে এগুলি কিছুটা আলাদা।

ডকুমেন্টেশন থেকে উদাহরণ ।

মডেল
ব্লগ টু এন্ট্রি একের সাথে একাধিক সম্পর্ক।

from django.db import models

class Blog(models.Model):
    ...

class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    pub_date = models.DateField()
    ...

অবজেক্টস
ধরে নিচ্ছি এখানে কিছু ব্লগ এবং প্রবেশের বিষয় রয়েছে।
এখানে চিত্র বর্ণনা লিখুন

প্রশ্নগুলি

Blog.objects.filter(entry__headline_contains='Lennon', 
    entry__pub_date__year=2008)
Blog.objects.filter(entry__headline_contains='Lennon').filter(
    entry__pub_date__year=2008)  
    

1 ম ক্যোয়ারির জন্য (একক ফিল্টার এক), এটি কেবল ব্লগ 1 এর সাথে মেলে।

২ য় ক্যোয়ারের জন্য (চেইন ফিল্টারগুলির একটি) এটি ব্লগ 1 এবং ব্লগ 2 ফিল্টার করে।
প্রথম ফিল্টার ক্যোরিসেটটি ব্লগ 1, ব্লগ 2 এবং ব্লগ 5 এ সীমাবদ্ধ করে; দ্বিতীয় ফিল্টারটি ব্লগের সেটটিকে আরও ব্লগ 1 এবং ব্লগ 2 এ সীমাবদ্ধ করে।

এবং আপনি এটা বুঝতে হবে

আমরা প্রতিটি ফিল্টার স্টেটমেন্ট দিয়ে ব্লগ আইটেমগুলি ফিল্টার করছি, এন্ট্রি আইটেমগুলি নয়।

সুতরাং, এটি এক নয়, কারণ ব্লগ এবং এন্ট্রি বহু-মূল্যবান সম্পর্ক।

তথ্যসূত্র: https://docs.djangoproject.com/en/1.8/topics/db/queries/#spanning-mult-valued-referencesship
যদি কিছু ভুল হয় তবে দয়া করে আমাকে সংশোধন করুন।

সম্পাদনা করুন: 1.1 লিঙ্কগুলি আর উপলভ্য না হওয়ায় v1.6 কে v1.8 এ পরিবর্তিত হয়েছে।


4
আপনি "ম্যাচ" এবং "ফিল্টার আউট" এর মধ্যে মিশে গেছেন বলে মনে হচ্ছে। যদি আপনি "এই ক্যোয়ারীটি ফেরত দেয়" তে আটকে থাকেন তবে এটি অনেক পরিষ্কার হয়ে যায়।
অরেঞ্জডগ

7

আপনি উত্পন্ন এসকিউএল বিবৃতিতে দেখতে পাচ্ছেন পার্থক্যটি "OR" নয় কারণ কিছু লোক সন্দেহ করতে পারে। WHOE এবং JOIN কে এভাবে স্থাপন করা হয়।

উদাহরণ 1 (একই যোগদানের টেবিল):

(উদাহরণস্বরূপ https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-mult--ued- সম্পর্কিত সম্পর্ক )

Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)

এটি আপনাকে এমন সমস্ত ব্লগকে দেবে যা দুজনের সাথেই একটি প্রবেশ রয়েছে (এন্ট্রি_ শিরোনাম _ কনটেনস = 'লেনন') এবং (এন্ট্রি__পব_ডেট__ ইয়ার = ২০০৮), যা আপনি এই কোয়েরি থেকে আশা করবেন। ফলাফল: {এন্ট্রি সহ হেডলাইন: 'লেননের জীবন', এন্ট্রি.পব_ডেট: '২০০৮'}

উদাহরণ 2 (শৃঙ্খলিত)

Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

এটি উদাহরণ 1 থেকে সমস্ত ফলাফল কভার করবে, তবে এটি কিছুটা আরও ফলাফল উত্পন্ন করবে। কারণ এটি প্রথমে সমস্ত ব্লগ (এন্ট্রি_ শিরোনাম _ কনটেনস = 'লেনন') দিয়ে ফিল্টার করে এবং তারপরে ফলাফল ফিল্টারগুলি (এন্ট্রি__পব_ডেট__ইয়ার = ২০০৮) থেকে।

সঙ্গে বই: পার্থক্য হচ্ছে এটি আপনাকে দেব মত ফলাফল হল {entry.headline: ' লেনন ', entry.pub_date: 2000}, {entry.headline: 'বিল', entry.pub_date: 2008 }

আপনার ক্ষেত্রে

আমি মনে করি এটি আপনার প্রয়োজন:

Book.objects.filter(inventory__user__profile__vacation=False, inventory__user__profile__country='BR')

এবং আপনি যদি ওআর ব্যবহার করতে চান তবে দয়া করে পড়ুন: https://docs.djangoproject.com/en/dev/topics/db/queries/#complex-lookups-with-q-objects


দ্বিতীয় উদাহরণটি আসলে সত্য নয়। সমস্ত শৃঙ্খলিত ফিল্টারগুলি কোয়েরি করা অবজেক্টগুলিতে প্রয়োগ করা হয়, অর্থাত তারা কোয়েরিতে একসাথে অ্যান্ডড হয়।
জান্নে

আমি বিশ্বাস করি যে উদাহরণ 2 সঠিক, এবং এটি প্রকৃতপক্ষে রেফারেন্স অনুসারে জাজানো অফিসিয়াল নথি থেকে নেওয়া ব্যাখ্যা explanation আমি সেরা ব্যাখ্যাকারী নাও হতে পারি এবং এর জন্য আমি ক্ষমা করে দিই। উদাহরণ 1 হ'ল একটি সরাসরি এবং যেমনটি আপনি সাধারণ এসকিউএল লেখায় প্রত্যাশা করেন। উদাহরণ 1 এর মতো কিছু দেয়: 'ব্লগ নির্বাচন করুন যেখানে এন্ট্রিতে যোগদান করুন। হেড_লাইন " লেনন " এবং এন্ট্রি.ইয়ার == ২০০৮ উদাহরণ 2 এর মতো কিছু দেয়:' নির্বাচন করুন ব্লগ জয়েন এন্ট্রি যেখানে এন্ট্রি.ইড_লিস্ট পছন্দ করুন " লেনন " ইউনিয়ন নির্বাচন করুন ব্লগ যেখানে প্রবেশ করুন সেখানে প্রবেশ করুন। হেড_লিস্ট " লেনন " "
জনি সাং

স্যার আপনি ঠিক বলেছেন। তাড়াহুড়ো করে আমি এই বিষয়টিটি মিস করেছি যে আমাদের ফিল্টারিং মানদণ্ডটি ব্লগের কাছে নয়, একের মধ্যে অনেকগুলি সম্পর্কের দিকে নির্দেশ করছে।
জান্নে 27'14

0

কখনও কখনও আপনি এক সাথে একাধিক ফিল্টার যোগ দিতে চান না:

def your_dynamic_query_generator(self, event: Event):
    qs \
    .filter(shiftregistrations__event=event) \
    .filter(shiftregistrations__shifts=False)

এবং নিম্নলিখিত কোডটি আসলে সঠিক জিনিসটি ফেরত দেবে না।

def your_dynamic_query_generator(self, event: Event):
    return Q(shiftregistrations__event=event) & Q(shiftregistrations__shifts=False)

আপনি এখন যা করতে পারেন তা এন্টোটেশন কাউন্ট ফিল্টার ব্যবহার করা।

এই ক্ষেত্রে আমরা সমস্ত শিফট গণনা করি যা একটি নির্দিষ্ট ইভেন্টের অন্তর্গত।

qs: EventQuerySet = qs.annotate(
    num_shifts=Count('shiftregistrations__shifts', filter=Q(shiftregistrations__event=event))
)

এরপরে আপনি টিকা দ্বারা ফিল্টার করতে পারেন।

def your_dynamic_query_generator(self):
    return Q(num_shifts=0)

এই সমাধানটি বড় ক্যোয়ারসেটেও সস্তা।

আশাকরি এটা সাহায্য করবে.

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.