django में कई तर्कों और चेन फिल्टर के साथ फिल्टर के बीच अंतर


जवाबों:


60

जैसा कि आप उत्पन्न SQL कथनों में देख सकते हैं कि अंतर "OR" नहीं है क्योंकि कुछ पर संदेह हो सकता है। यह कैसे WHERE और JOIN रखा गया है।

उदाहरण 1 (उसी तालिका में शामिल हुए): https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships से

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

इससे आपको उन सभी ब्लॉग्स मिल जाएंगे जिनमें दोनों के साथ एक प्रविष्टि है (entry__headline__contains='Lennon') AND (entry__pub_date__year=2008), जो कि आप इस क्वेरी से उम्मीद करेंगे।

परिणाम:

Blog with {entry.headline: 'Life of Lennon', entry.pub_date: '2008'}

उदाहरण 2 (जंजीर)

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

यह उदाहरण 1 से सभी परिणामों को कवर करेगा, लेकिन यह थोड़ा और परिणाम उत्पन्न करेगा। क्योंकि यह पहले सभी ब्लॉग को फ़िल्टर करता है (entry__headline__contains='Lennon')और फिर परिणाम फ़िल्टर से (entry__pub_date__year=2008)

अंतर यह है कि यह आपको परिणाम भी देगा जैसे:

एकाधिक प्रविष्टियों के साथ एक एकल ब्लॉग

{entry.headline: '**Lennon**', entry.pub_date: 2000}, 
{entry.headline: 'Bill', entry.pub_date: **2008**}

जब पहली फ़िल्टर का मूल्यांकन किया गया था तो पहली प्रविष्टि (भले ही इसमें अन्य प्रविष्टियाँ हों जो मेल नहीं खाती हैं) के कारण पुस्तक शामिल है। जब दूसरे फ़िल्टर का मूल्यांकन किया जाता है तो पुस्तक को दूसरी प्रविष्टि के कारण शामिल किया जाता है।

एक तालिका: लेकिन यदि क्वेरी में युजी और डीटीइंग से उदाहरण जैसी तालिकाओं को शामिल नहीं किया गया है। परिणाम वही है।


21
मुझे लगता है कि मैं आज सुबह बस सघन हूं, लेकिन यह वाक्य मुझे भ्रमित करता है: "क्योंकि यह पहले सभी ब्लॉगों को फ़िल्टर करता है (entry__headline__contains='Lennon')और फिर परिणाम फिल्टरों से (entry__pub_date__year=2008)" यदि "फिर" परिणाम से "सटीक होता है, तो यह कुछ के साथ क्यों शामिल होगा entry.headline == 'Bill'.. .wouldn't entry__headline__contains='Lennon'बाहर फिल्टर Billउदाहरण?
डस्टिन वायट

7
मैं भी उलझन में हूं। ऐसा लगता है कि यह उत्तर सिर्फ गलत है, लेकिन इसमें 37 उत्थान हैं ...
कार्मिक

1
यह उत्तर भ्रामक और भ्रमित करने वाला है, ध्यान दें उपरोक्त केवल तभी सही है जब युजी के उत्तर में उल्लिखित M2M संबंधों का उपयोग करते हुए फ़िल्टर किया जाए। प्रमुख बिंदु यह है कि प्रत्येक फ़िल्टर स्टेटमेंट के साथ ब्लॉग आइटम को फ़िल्टर किया जा रहा है, एंट्री आइटम को नहीं।
18:05 पर theannouncer

1
क्योंकि प्रति ब्लॉग में संभवतः कई प्रविष्टियाँ होती हैं। भाषा सही है। यदि आप सभी चलते हुए टुकड़ों को ध्यान में नहीं रखते हैं तो यह अवधारणा भ्रामक हो सकती है।
डायलनयुंग

@DustinWyatt मैं भी आपके जैसे ही प्रश्न थे, लेकिन मुझे अंततः मिल गया है! कृपया इस पेज पर नीचे ब्रिजेश चौहान द्वारा लिखित कर्मचारी और आश्रित उदाहरण देखें और आपको यह भी मिल जाएगा।
TheQuestionMan

33

वह मामला जिसमें "कई तर्क फ़िल्टर-क्वेरी" के परिणाम "जंजीर-फ़िल्टर-क्वेरी" से भिन्न होते हैं, निम्नलिखित हैं:

संदर्भित वस्तुओं के आधार पर संदर्भित वस्तुओं का चयन करना और संबंध एक-से-कई (या कई-से-कई) हैं।

कई फिल्टर:

    Referenced.filter(referencing1_a=x, referencing1_b=y)
    #  same referencing model   ^^                ^^

जंजीर फिल्टर:

    Referenced.filter(referencing1_a=x).filter(referencing1_b=y)

दोनों प्रश्न अलग-अलग परिणाम उत्पन्न कर सकते हैं:
यदि अधिक है तो संदर्भित-मॉडल में Referencing1एक पंक्ति संदर्भित-मॉडल में एक ही पंक्ति को संदर्भित कर सकती है Referenced। यह मामला हो सकता है Referenced: Referencing1या तो 1: एन (एक से कई) या एन: एम (कई से कई) संबंध-जहाज हैं।

उदाहरण:

गौर करें कि मेरे आवेदन my_companyमें दो मॉडल हैं Employeeऔर Dependent। एक कर्मचारी my_companyआश्रितों से अधिक हो सकता है (दूसरे शब्दों में एक आश्रित एक एकल कर्मचारी का बेटा / बेटी हो सकता है, जबकि एक कर्मचारी के एक से अधिक बेटे / बेटी हो सकते हैं)।
एह, पति-पत्नी की तरह मान लेना दोनों में काम नहीं कर सकते my_company। मैंने 1: m उदाहरण लिया

तो, Employeeसंदर्भित-मॉडल जिसे अधिक संदर्भित किया जा सकता है तो Dependentवह संदर्भ-मॉडल है। अब संबंध-स्थिति पर विचार करें:

Employee:        Dependent:
+------+        +------+--------+-------------+--------------+
| name |        | name | E-name | school_mark | college_mark |
+------+        +------+--------+-------------+--------------+
| A    |        | a1   |   A    |          79 |           81 |
| B    |        | b1   |   B    |          80 |           60 |
+------+        | b2   |   B    |          68 |           86 |
                +------+--------+-------------+--------------+  

आश्रित a1कर्मचारी को संदर्भित करता है A, और आश्रित b1, b2कर्मचारी के लिए संदर्भ B

अब मेरी क्वेरी है:

उन सभी कर्मचारियों का पता लगाएं, जिनके बेटे / बेटी के कॉलेज और स्कूल दोनों में अंतर के निशान (=> 75%) हैं?

>>> Employee.objects.filter(dependent__school_mark__gte=75,
...                         dependent__college_mark__gte=75)

[<Employee: A>]

आउटपुट 'ए' डिपेंडेंट 'ए 1' है, जिसमें कॉलेज और स्कूल दोनों में अंतर है, कर्मचारी 'ए' पर निर्भर है। नोट 'B' इसलिए नहीं चुना गया है क्योंकि 'B' के बच्चे के nether में कॉलेज और स्कूल दोनों में भेद के निशान हैं। संबंधपरक बीजगणित:

कर्मचारी (school_mark> = 75 और college_mark> = 75) आश्रित

दूसरे मामले में, मुझे एक प्रश्न चाहिए:

उन सभी कर्मचारियों को खोजें जिनके कुछ आश्रितों के कॉलेज और स्कूल में भेद के निशान हैं?

>>> Employee.objects.filter(
...             dependent__school_mark__gte=75
...                ).filter(
...             dependent__college_mark__gte=75)

[<Employee: A>, <Employee: B>]

इस बार 'बी' का चयन इसलिए भी किया गया क्योंकि 'बी' के दो बच्चे हैं (एक से अधिक!), एक का स्कूल 'बी 1' में अंतर है और दूसरे का कॉलेज 'बी 2' में भी अंतर है।
फ़िल्टर के आदेश से कोई फर्क नहीं पड़ता कि हम क्वेरी के ऊपर भी लिख सकते हैं:

>>> Employee.objects.filter(
...             dependent__college_mark__gte=75
...                ).filter(
...             dependent__school_mark__gte=75)

[<Employee: A>, <Employee: B>]

परिणाम वही है! संबंधपरक बीजगणित हो सकता है:

(कर्मचारी Emp (school_mark> = 75) आश्रित) _ (college_mark> = 75) आश्रित

निम्नलिखित नोट करें:

dq1 = Dependent.objects.filter(college_mark__gte=75, school_mark__gte=75)
dq2 = Dependent.objects.filter(college_mark__gte=75).filter(school_mark__gte=75)

समान परिणाम: [<Dependent: a1>]

मैं टारगेट SQL क्वेरी का उपयोग करके Django द्वारा उत्पन्न किया गया है print qd1.queryऔर print qd2.queryदोनों समान हैं (Django 1.6)।

लेकिन शब्दार्थ दोनों मेरे लिए अलग हैं । पहला साधारण खंड जैसा दिखता है mark [school_mark> = 75 और college_mark> = 75] (आश्रित) और दूसरा धीमा नेस्टेड क्वेरी की तरह: σ [school_mark> = 75][college_mark> = 75] (आश्रित))।

यदि किसी को कोड @ कोडपैड की आवश्यकता है

btw, यह दस्तावेज़ीकरण में दिया गया है @ बहु-मूल्यवान रिश्तों को मैंने अभी एक उदाहरण जोड़ा है, मुझे लगता है कि यह किसी नए व्यक्ति के लिए उपयोगी होगा।


4
इस सहायक स्पष्टीकरण के लिए धन्यवाद, यह प्रलेखन में एक से बेहतर है जो बिल्कुल भी स्पष्ट नहीं है।
विम

1
डिपेंडेंट को सीधे फ़िल्टर करने के बारे में अंतिम निशान सुपर मददगार है। यह दर्शाता है कि परिणामों में परिवर्तन निश्चित रूप से केवल तब होता है जब आप कई-कई संबंधों से गुजरते हैं। यदि आप किसी तालिका को सीधे क्वेरी करते हैं, तो फिल्टर का पीछा करना दो बार कंघी करने जैसा है।
क्रिस

20

अधिकांश समय, क्वेरी के लिए परिणामों का एक ही संभव सेट होता है।

जब आप एम 2 एम के साथ काम कर रहे हों तो चेनिंग फिल्टर का उपयोग होता है:

इस पर विचार करो:

# will return all Model with m2m field 1
Model.objects.filter(m2m_field=1) 

# will return Model with both 1 AND 2    
Model.objects.filter(m2m_field=1).filter(m2m_field=2) 

# this will NOT work
Model.objects.filter(Q(m2m_field=1) & Q(m2m_field=2))

अन्य उदाहरणों का स्वागत है।


4
एक और उदाहरण: यह केवल एम 2 एम तक सीमित नहीं है, यह एक से कई के साथ भी हो सकता है - रिवर्स लुकअप जैसे उदाहरण के लिए संबंधित_नाम का उपयोग करके फॉरेनके पर
wim

आपके व्याख्या के लिये धन्यवाद! इससे पहले, मैंने सोचा था कि अंतिम और 2 उदाहरण समान हैं, इसलिए अंतिम उदाहरण मेरे लिए (गलत क्वेरी परिणाम) काम नहीं था, और मैंने खोजों में बहुत समय बिताया। दूसरा उदाहरण मेरे लिए बहुत उपयोगी है। इसके अलावा, जैसा कि विम ने कहा, यह मेरे मामले में उल्टे एक से कई संबंधों के साथ प्रयोग करने योग्य है।
zen11625

12

प्रदर्शन अंतर बहुत बड़ा है। यह कोशिश करो और देखो।

Model.objects.filter(condition_a).filter(condition_b).filter(condition_c)

की तुलना में आश्चर्यजनक रूप से धीमा है

Model.objects.filter(condition_a, condition_b, condition_c)

जैसा कि प्रभावी Django ORM में उल्लेख किया गया है ,

  • QuerySets स्मृति में स्थिति बनाए रखता है
  • चेनिंग क्लोनिंग को ट्रिगर करता है, उस स्थिति को दोहराता है
  • दुर्भाग्य से, QuerySets बहुत सारे राज्य बनाए रखता है
  • यदि संभव हो, तो एक से अधिक फ़िल्टर न करें

8

तुलना करने के लिए कच्चे sql प्रश्नों को देखने के लिए आप कनेक्शन मॉड्यूल का उपयोग कर सकते हैं। जैसा कि युजी द्वारा समझाया गया है, अधिकांश भाग के लिए वे समकक्ष हैं जैसा कि यहां दिखाया गया है:

>>> from django.db import connection
>>> samples1 = Unit.objects.filter(color="orange", volume=None)
>>> samples2 = Unit.objects.filter(color="orange").filter(volume=None)
>>> list(samples1)
[]
>>> list(samples2)
[]
>>> for q in connection.queries:
...     print q['sql']
... 
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange  AND `samples_unit`.`volume` IS NULL)
SELECT `samples_unit`.`id`, `samples_unit`.`color`, `samples_unit`.`volume` FROM `samples_unit` WHERE (`samples_unit`.`color` = orange  AND `samples_unit`.`volume` IS NULL)
>>> 

3

यह उत्तर Django 3.1 पर आधारित है।

वातावरण

मॉडल

class Blog(models.Model):
    blog_id = models.CharField()

class Post(models.Model):
    blog_id  = models.ForeignKeyField(Blog)
    title    = models.CharField()
    pub_year = models.CharField() # Don't use CharField for date in production =]

डेटाबेस तालिकाओं

यहाँ छवि विवरण दर्ज करें

फिल्टर बुलाते हैं

Blog.objects.filter(post__title="Title A", post__pub_year="2020")
# Result: <QuerySet [<Blog: 1>]>

Blog.objects.filter(post__title="Title A").filter(post_pub_date="2020)
# Result: <QuerySet [<Blog: 1>, [<Blog: 2>]>

व्याख्या

इससे पहले कि मैं आगे कुछ भी शुरू करूं, मुझे ध्यान देना होगा कि यह उत्तर उन परिस्थितियों पर आधारित है जो ऑब्जेक्ट्स को फ़िल्टर करने के लिए "ManyToManyField" या रिवर्स "ForeignKey" का उपयोग करती हैं।

यदि आप वस्तुओं को फ़िल्टर करने के लिए एक ही तालिका या "OneToOneField" का उपयोग कर रहे हैं, तो "एकाधिक तर्क फ़िल्टर" या "फ़िल्टर-श्रृंखला" का उपयोग करने के बीच कोई अंतर नहीं होगा। वे दोनों एक "और" शर्त फ़िल्टर की तरह काम करेंगे।

"एकाधिक तर्क फ़िल्टर" और "फ़िल्टर-श्रृंखला" का उपयोग करने के तरीके को समझने के लिए सीधे आगे का तरीका "ManyToManyField" या एक रिवर्स "ForeignKey" फ़िल्टर को याद रखना है, "एकाधिक तर्क फ़िल्टर" एक "और" स्थिति और "फ़िल्टर" है -चैन "एक" या "स्थिति है।

"एकाधिक तर्क फ़िल्टर" और "फ़िल्टर-श्रृंखला" को इतना अलग बनाने का कारण यह है कि वे अलग-अलग ज्वाइन टेबल से परिणाम प्राप्त करते हैं और क्वेरी स्टेटमेंट में विभिन्न स्थिति का उपयोग करते हैं।

"एकाधिक तर्क फ़िल्टर" "पोस्ट " का उपयोग करें सार्वजनिक वर्ष की पहचान करने के लिए "Public_Year" = '2020'

SELECT *
FROM "Book" 
INNER JOIN ("Post" ON "Book"."id" = "Post"."book_id")
WHERE "Post"."Title" = 'Title A'
AND "Post"."Public_Year" = '2020'

"फ़िल्टर-चेन" डेटाबेस क्वेरी "T1" का उपयोग करती है सार्वजनिक वर्ष की पहचान करने के लिए "Public_Year" = '2020'

SELECT *
FROM "Book" 
INNER JOIN "Post" ON ("Book"."id" = "Post"."book_id")
INNER JOIN "Post" T1 ON ("Book"."id" = "T1"."book_id")
WHERE "Post"."Title" = 'Title A'  
AND "T1"."Public_Year" = '2020'

लेकिन अलग-अलग स्थितियां परिणाम को क्यों प्रभावित करती हैं?

मेरा मानना ​​है कि हममें से ज्यादातर लोग, जो मेरे साथ इस पृष्ठ पर आते हैं =], पहले "मल्टीपल आर्ग्यूमेंट फ़िल्टर" और "फ़िल्टर-चेन" का उपयोग करते समय एक ही धारणा है।

जो हम मानते हैं कि परिणाम को एक तालिका से प्राप्त किया जाना चाहिए जैसे कि "एकाधिक तर्क फ़िल्टर" के लिए सही है। इसलिए यदि आप "एकाधिक तर्क फ़िल्टर" का उपयोग कर रहे हैं, तो आपको अपनी अपेक्षा के अनुसार परिणाम मिलेगा।

यहाँ छवि विवरण दर्ज करें

लेकिन "फ़िल्टर-चेन" के साथ काम करते समय, Django एक अलग क्वेरी स्टेटमेंट बनाता है जो उपरोक्त तालिका को निम्नलिखित में बदलता है। साथ ही, "सार्वजनिक वर्ष" को क्वेरी विवरण में परिवर्तन के कारण "पोस्ट" अनुभाग के बजाय "T1" अनुभाग के तहत पहचाना जाता है।

यहाँ छवि विवरण दर्ज करें

लेकिन यह अजीब "फिल्टर-चेन" टेबल आरेख में कहां से आता है?

मैं एक डेटाबेस विशेषज्ञ नहीं हूँ। नीचे दिए गए स्पष्टीकरण को मैंने डेटाबेस की समान संरचना बनाने के बाद अब तक समझा है और उसी क्वेरी स्टेटमेंट के साथ परीक्षण किया है।

निम्न आरेख दिखाएगा कि यह अजीब "फ़िल्टर-चेन" टेबल आरेख से कैसे जुड़ता है।

यहाँ छवि विवरण दर्ज करें

यहाँ छवि विवरण दर्ज करें

डेटाबेस पहले "ब्लॉग" और "पोस्ट" टेबल की पंक्ति को एक-एक करके मेल करके एक टेबल बना देगा।

उसके बाद, डेटाबेस अब उसी मिलान प्रक्रिया को फिर से करता है लेकिन "T1" तालिका से मिलान करने के लिए चरण 1 परिणाम तालिका का उपयोग करता है जो कि केवल समान "पोस्ट" तालिका है।

और इस तरह यह अजीब "फिल्टर-चेन" टेबल आरेख से जुड़ता है।

निष्कर्ष

तो दो चीजें "मल्टीपल अर्ग्युमेंट्स फिल्टर" और "फिल्टर-चेन" को अलग बनाती हैं।

  1. Django "एकाधिक तर्क फ़िल्टर" और "फ़िल्टर-श्रृंखला" के लिए अलग-अलग क्वेरी स्टेटमेंट बनाते हैं जो "एकाधिक तर्क फ़िल्टर" और "फ़िल्टर-श्रृंखला" परिणाम विभिन्न तालिकाओं से आते हैं।
  2. "फ़िल्टर-चेन" क्वेरी स्टेटमेंट "मल्टीपल आर्ग्युमेंट्स फ़िल्टर" की तुलना में एक अलग जगह से स्थिति की पहचान करता है।

यह याद रखने का गंदा तरीका कि इसका "मल्टीपल आर्ग्यूमेंट फ़िल्टर" कैसे उपयोग किया जाता है, एक "और" स्थिति है और "फ़िल्टर-चेन" एक "ORT" स्थिति है, जबकि एक "ManyToManyField" या रिवर्स "ForeignKey" फ़िल्टर है।


2

यदि आप इस पेज पर अंत में देख रहे हैं कि गतिशील रूप से कई चेनिंग फिल्टर के साथ django क्वेरी को कैसे बनाया जाए, लेकिन आपको ANDइसके बजाय फ़िल्टर की आवश्यकता होती है OR, तो Q ऑब्जेक्ट का उपयोग करने पर विचार करें

एक उदाहरण:

# First filter by type.
filters = None
if param in CARS:
  objects = app.models.Car.objects
  filters = Q(tire=param)
elif param in PLANES:
  objects = app.models.Plane.objects
  filters = Q(wing=param)

# Now filter by location.
if location == 'France':
  filters = filters & Q(quay=location)
elif location == 'England':
  filters = filters & Q(harbor=location)

# Finally, generate the actual queryset
queryset = objects.filter(filters)

यदि इफ या एलिफ पारित नहीं होता है, तो फिल्टर चर कोई भी नहीं होगा और फिर आपको टाइप करें: unsupported operand type (s) for &: 'noneType' और 'Q'। मैंने फिल्टर्स को फिल्टर्स के साथ = Q ()
cwhisperer

0

यदि एक और बी की आवश्यकता है

and_query_set = Model.objects.filter(a=a, b=b)

यदि आवश्यक हो तो b

chaied_query_set = Model.objects.filter(a=a).filter(b=b)

आधिकारिक दस्तावेज: https://docs.djangoproject.com/en/dev/topics/db/queries/#spanning-multi-valued-relationships

संबंधित पोस्ट: Django में कई फिल्टर () का पीछा करते हुए, यह एक बग है?


-4

उदाहरण के लिए, जब आपके पास अपनी संबंधित वस्तु के लिए अनुरोध होता है, तो अंतर होता है

class Book(models.Model):
    author = models.ForeignKey(Author)
    name = models.ForeignKey(Region)

class Author(models.Model):
    name = models.ForeignKey(Region)

निवेदन

Author.objects.filter(book_name='name1',book_name='name2')

खाली सेट देता है

और अनुरोध करें

Author.objects.filter(book_name='name1').filter(book_name='name2')

उन लेखकों को लौटाता है जिनके पास 'name1' और 'name2' दोनों की किताबें होती हैं

जानकारी के लिए https://docs.djangoproject.com/en/dev/topics/db/queries/#s-spanning-multi-valued-relationships पर देखें


5
Author.objects.filter(book_name='name1',book_name='name2')यह भी मान्य अजगर नहीं है, यह होगाSyntaxError: keyword argument repeated
wim

1
Book_name को वास्तव में कहाँ परिभाषित किया गया है? क्या आपका मतलब book_set__name है?
डायलनयुंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.