জঙ্গোতে গ্রুপ হিসাবে কীভাবে জিজ্ঞাসা করবেন?


332

আমি একটি মডেল জিজ্ঞাসা:

Members.objects.all()

এবং এটি ফিরে আসে:

Eric, Salesman, X-Shop
Freddie, Manager, X2-Shop
Teddy, Salesman, X2-Shop
Sean, Manager, X2-Shop

আমি যা চাই তা হল group_byআমার ডেটাবেজে কোনও জিজ্ঞাসা চালানোর জন্য সেরা জ্যাঙ্গো উপায়টি জানা , যেমন:

Members.objects.all().group_by('designation')

যা অবশ্যই কাজ করে না। আমি জানি আমরা কিছু কৌশল করতে পারি django/db/models/query.py, তবে প্যাচ না করে কীভাবে এটি করা যায় তা জানতে আমি আগ্রহী।

উত্তর:


483

যদি আপনি একত্রিতকরণ করতে চান তবে আপনি ওআরএমের সংহত বৈশিষ্ট্যগুলি ব্যবহার করতে পারেন :

from django.db.models import Count
Members.objects.values('designation').annotate(dcount=Count('designation'))

এর অনুরূপ ক্যোয়ারিতে ফলাফল results

SELECT designation, COUNT(designation) AS dcount
FROM members GROUP BY designation

এবং আউটপুট ফর্ম হতে হবে

[{'designation': 'Salesman', 'dcount': 2}, 
 {'designation': 'Manager', 'dcount': 2}]

6
@ হ্যারি: আপনি এটি চেইন করতে পারেন। এর মতো কিছু:Members.objects.filter(date=some_date).values('designation').annotate(dcount=Count('designation'))
এলি

57
আমার একটি প্রশ্ন আছে, এই ক্যোয়ারীটি কেবল পদবি এবং ডেসকাউন্ট ফেরত আসবে, আমি যদি টেবিলের অন্যান্য মানগুলিও পেতে চাই?
এজে

19
মনে রাখবেন যে আপনার বাছাই করা যদি পদবী ব্যতীত অন্য কোনও ক্ষেত্র হয় তবে এটি সাজানোর পুনরায় সেট না করে কাজ করবে না। দেখুন stackoverflow.com/a/1341667/202137
Gidgidonihah

12
@ জিডজিডোনিহাহ সত্য, উদাহরণটি পড়তে হবেMembers.objects.order_by('disignation').values('designation').annotate(dcount=Count('designation'))
বুজুনিক্স

7
আমার একটি প্রশ্ন আছে, এই ক্যোয়ারীটি কেবল পদবি এবং ডেসকাউন্ট ফেরত আসবে, আমি যদি টেবিলের অন্যান্য মানগুলিও পেতে চাই?
ইয়ান 叶

55

একটি সহজ সমাধান, তবে সঠিক উপায় নয় কাঁচা এসকিউএল ব্যবহার করা :

results = Members.objects.raw('SELECT * FROM myapp_members GROUP BY designation')

আর একটি সমাধান group_byসম্পত্তি ব্যবহার করা হয় :

query = Members.objects.all().query
query.group_by = ['designation']
results = QuerySet(query=query, model=Members)

আপনার ফলাফলগুলি পুনরুদ্ধার করতে আপনি এখন ফলাফলের পরিবর্তনশীলটির সাথে পুনরাবৃত্তি করতে পারেন। নোটটি group_byনথিভুক্ত নয় এবং ভবিষ্যতে জ্যাঙ্গোর সংস্করণে পরিবর্তিত হতে পারে Note

এবং ... আপনি কেন ব্যবহার করতে চান group_by? আপনি যদি একত্রিতকরণ ব্যবহার না করেন তবে আপনি order_byঅভিন্ন ফলাফল অর্জন করতে ব্যবহার করতে পারেন ।


অর্ডার_বি ব্যবহার করে কীভাবে করবেন তা দয়া করে আমাকে বলতে পারবেন ??
কেবলমাত্র মার্শ

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

আরে এটি দুর্দান্ত - আপনি কীভাবে এটি নির্ধারণ করতে পারেন
এক্সিকিউট_এসকিউএল

8
নোট করুন এটি আর জ্যাঙ্গো 1.9 এ কাজ করে না। stackoverflow.com/questions/35558120/...
grokpot

1
এটি ওআরএম ব্যবহারের হ্যাক-ইশ উপায় way পুরানোগুলিতে ম্যানুয়ালি পাস করার জন্য আপনাকে নতুন ক্যোয়ারসেটগুলি ইনস্ট্যান্ট করতে হবে না।
ইয়ান কির্কপ্যাট্রিক

32

আপনি regroupবৈশিষ্ট্য দ্বারা গোষ্ঠী করতে টেমপ্লেট ট্যাগ ব্যবহার করতে পারেন । দস্তাবেজগুলি থেকে:

cities = [
    {'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
    {'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
    {'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
    {'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
    {'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]

...

{% regroup cities by country as country_list %}

<ul>
    {% for country in country_list %}
        <li>{{ country.grouper }}
            <ul>
            {% for city in country.list %}
                <li>{{ city.name }}: {{ city.population }}</li>
            {% endfor %}
            </ul>
        </li>
    {% endfor %}
</ul>

এটা এমন দেখতে:

  • ভারত
    • মুম্বই: 19,000,000
    • কলকাতা: 15,000,000
  • আমেরিকা
    • নিউ ইয়র্ক: 20,000,000
    • শিকাগো: 7,000,000
  • জাপান
    • টোকিও: 33,000,000

এটি QuerySetআমার বিশ্বাসের ক্ষেত্রেও কাজ করে ।

উত্স: https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#regroup

সম্পাদনা: নোটটি regroupট্যাগটি তেমন কাজ করে না যেমনটি আপনি প্রত্যাশা করবেন যদি আপনার অভিধানের তালিকা কী-বাছাই করা না থাকে। এটি পুনরাবৃত্তভাবে কাজ করে। সুতরাং আপনার তালিকাটি (বা ক্যোয়ারী সেট) regroupট্যাগ করে পাসওয়ার্ড দেওয়ার আগে গ্রেপারের কী দ্বারা বাছাই করুন ।


1
এটি নিখুঁত! এটি করার সহজ উপায়টির জন্য আমি অনেক অনুসন্ধান করেছি। এবং এটি ক্যোয়ারীটগুলিতেও কাজ করে, আমি এটি এটিই ব্যবহার করি।
কারমেনা

1
এটি সম্পূর্ণ ভুল যদি আপনি ডাটাবেসের বড় সেট ডেটা থেকে পড়েন এবং তারপরে কেবল একত্রিত মানগুলি ব্যবহার করেন।
সাওওমির লেনার্ট

@ সাওওমির্নার্ন্ট নিশ্চিত করুন, এটি সরাসরি ডিবি ক্যোয়ারির মতো দক্ষ নাও হতে পারে। তবে সাধারণ ব্যবহারের ক্ষেত্রে এটি দুর্দান্ত সমাধান হতে পারে
ইনোস্টিয়া

ফলাফলটি টেমপ্লেটে প্রদর্শিত হলে এটি কাজ করবে। তবে, জসনরেসপোনস বা অন্যান্য অপ্রত্যক্ষ প্রতিক্রিয়া। এই সমাধান কাজ করবে না।
উইলি স্যাট্রিও নগ্রোহো

1
@Willysatrionugroho আপনি একটি দৃশ্য এটা করতে চেয়েছিলেন, উদাহরণস্বরূপ, stackoverflow.com/questions/477820/... আপনার জন্য কাজ করতে পারে
inostia

7

এই স্নিপেটে উদাহরণ হিসাবে আপনাকে কাস্টম এসকিউএল করা দরকার:

সাবকিউয়ের মাধ্যমে কাস্টম এসকিউএল

অথবা অনলাইন জ্যাঙ্গো ডক্সে প্রদর্শিত কাস্টম ম্যানেজারে:

অতিরিক্ত ব্যবস্থাপক পদ্ধতি যুক্ত করা হচ্ছে


1
বৃত্তাকার-ট্রিপ সমাধান ধরণের। আমি এটি ব্যবহার করতে পারতাম, যদি আমার এটির কিছু বাড়তি ব্যবহার হত। তবে এখানে আমার কেবলমাত্র প্রতি পদে সদস্য সংখ্যা দরকার তা সবই।
কেবলমাত্র মার্শ

সমস্যা নেই. আমি 1.1 সমষ্টিগত বৈশিষ্ট্যগুলি উল্লেখ করার কথা ভেবেছিলাম কিন্তু আপনি মুক্তির সংস্করণটি ব্যবহার করছেন এমন অনুমানটি করেছেন :)
ভ্যান গালে

এগুলি কাঁচা ক্যোয়ারীগুলি ব্যবহার করার বিষয়ে, যা জ্যাঙ্গোর ওআরএমের দুর্বলতা দেখায়।
সাওওমির লেনার্ট

5

জ্যাঙ্গো কোয়েরি করে ফ্রি গ্রুপকে সমর্থন করে না । আমি খুব খারাপ উপায়ে এটি শিখেছি। ওআরএম কাস্টম এসকিউএল ব্যবহার না করে আপনি যা করতে চান তার মতো স্টাফ সমর্থন করতে ডিজাইন করা হয়নি। আপনি সীমাবদ্ধ:

  • RAW sQL (যেমন MyModel.objects.raw ())
  • cr.execute বাক্যগুলি (এবং ফলাফলটি একটি হাতে তৈরি বিশ্লেষণ)
  • .annotate() (বাক্য অনুসারে গোষ্ঠীটি শিশু নীতিমালায় .annotate () এর জন্য করা হয়, উদাহরণস্বরূপ লাইন_কাউন্ট = গণনা ('লাইন')) এর মতো)।

ক্যোরিসেটের মাধ্যমে qsআপনি কল করতে পারেন qs.query.group_by = ['field1', 'field2', ...]তবে আপনি কী ক্যোয়ারীটি সম্পাদনা করছেন তা যদি আপনি জানেন না এবং কোয়েরিसेट অবজেক্টটির অভ্যন্তরীণ অংশটি কাজ করবে না এবং কোনও কাজ করবে না তার কোনও গ্যারান্টি না থাকলে এটি ঝুঁকিপূর্ণ। তদ্ব্যতীত, এটি একটি অভ্যন্তরীণ (অননুমোদিত) এপিআই যা আপনার ভবিষ্যতে জ্যাঙ্গো সংস্করণগুলির সাথে সামঞ্জস্যপূর্ণ না হওয়ার ঝুঁকি নিয়ে সরাসরি অ্যাক্সেস করা উচিত নয়।


প্রকৃতপক্ষে আপনি কেবল নিখরচায় গ্রুপ-বাই সীমাবদ্ধ না তাই জ্যাঙ্গো ওআরএম এর পরিবর্তে এসকিউএএলএলচেমি ব্যবহার করে দেখুন।
সাওওমির লেনার্ট

5

এমন মডিউল রয়েছে যা আপনাকে জ্যাঙ্গো মডেলগুলিকে গোষ্ঠী করতে দেয় এবং ফলাফলের মধ্যে কোয়েরী সেট নিয়ে এখনও কাজ করতে পারে: https://github.com/kako-nawao/django-group-by

উদাহরণ স্বরূপ:

from django_group_by import GroupByMixin

class BookQuerySet(QuerySet, GroupByMixin):
    pass

class Book(Model):
    title = TextField(...)
    author = ForeignKey(User, ...)
    shop = ForeignKey(Shop, ...)
    price = DecimalField(...)

class GroupedBookListView(PaginationMixin, ListView):
    template_name = 'book/books.html'
    model = Book
    paginate_by = 100

    def get_queryset(self):
        return Book.objects.group_by('title', 'author').annotate(
            shop_count=Count('shop'), price_avg=Avg('price')).order_by(
            'name', 'author').distinct()

    def get_context_data(self, **kwargs):
        return super().get_context_data(total_count=self.get_queryset().count(), **kwargs)

'বই / books.html'

<ul>
{% for book in object_list %}
    <li>
        <h2>{{ book.title }}</td>
        <p>{{ book.author.last_name }}, {{ book.author.first_name }}</p>
        <p>{{ book.shop_count }}</p>
        <p>{{ book.price_avg }}</p>
    </li>
{% endfor %}
</ul>

annotate/ aggregateবেসিক জ্যাঙ্গো প্রশ্নের সাথে পার্থক্য হ'ল সম্পর্কিত ক্ষেত্রের বৈশিষ্ট্যগুলির ব্যবহার, যেমন book.author.last_name

একসাথে গোষ্ঠীভুক্ত দৃষ্টান্তগুলির পিকেগুলির যদি আপনার প্রয়োজন হয় তবে নিম্নলিখিত টিকাটি যুক্ত করুন:

.annotate(pks=ArrayAgg('id'))

দ্রষ্টব্য: ArrayAggএকটি পোস্টগ্র্যাসের নির্দিষ্ট ফাংশন, জ্যাঙ্গো ১.৯ থেকে পরবর্তী: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/aggregates/#arrayagg


এই জ্যাঞ্জো-গ্রুপ-বাইvalues পদ্ধতিটির বিকল্প । এটি আমার মনে হয় ভিন্ন উদ্দেশ্যে।
LShi

1
@LShi এটি মানগুলির বিকল্প নয়, অবশ্যই নয় not valuesএসকিউএল selectথাকা অবস্থায় group_byএসকিউএল হয় group by(নামটি ইঙ্গিত দেয় ...)। ডাউনটা কেন? জটিল group_byবিবৃতি বাস্তবায়নের জন্য আমরা উত্পাদনে এ জাতীয় কোড ব্যবহার করছি ।
রিসাদিনহা

এর ডকটি বলেছে group_by"বেশিরভাগ মান পদ্ধতির মতো আচরণ করে তবে একটি পার্থক্যের সাথে ..." ডকটি এসকিউএল GROUP BYএবং এটি ব্যবহারের ক্ষেত্রে উল্লেখ করে না যে এটি এসকিউএল এর সাথে কিছু করার আছে তা বোঝায় না GROUP BY। কেউ এটি পরিষ্কার করে দিলে আমি ডাউন-ভোটটি ফিরিয়ে আনব, তবে ডকটি সত্যই বিভ্রান্তিকর।
LShi

এর জন্য দস্তাবেজটিvalues পড়ার পরে , আমি খুঁজে পেলাম যে valuesনিজে থেকেই একটি গ্রুপের মতো কাজ করে। এটা আমার দোষ. আমি মনে করি itertools.groupbyযখন valuesঅপ্রতুল হয় তখন এই জ্যাঙ্গো-গ্রুপ-বাইয়ের চেয়ে এটি ব্যবহার করা সহজ ।
LShi

1
এটা করতে অসম্ভব group byএকটি সহজ উপরের মতো values-সঙ্গে বা ছাড়া কল annotateএবং ডাটাবেস থেকে সবকিছু আনার সময় ছাড়া। আপনার itertools.groupbyছোট ছোট ডেটাসেটের জন্য কাজ করার পরামর্শটি কিন্তু আপনি সম্ভবত হাজার হাজার ডেটাসেটের জন্য নয় যা আপনি পৃষ্ঠাটি করতে চান। অবশ্যই, সেই সময়ে আপনাকে একটি বিশেষ অনুসন্ধান সূচী সম্পর্কে ভাবতে হবে যা যেভাবেই তৈরি (ইতিমধ্যে গোষ্ঠীযুক্ত) ডেটা রয়েছে।
রিসাদিনহা

0

ডকুমেন্ট বলছেন যে আপনি queryset গ্রুপে মান ব্যবহার করতে পারেন।

class Travel(models.Model):
    interest = models.ForeignKey(Interest)
    user = models.ForeignKey(User)
    time = models.DateTimeField(auto_now_add=True)

# Find the travel and group by the interest:

>>> Travel.objects.values('interest').annotate(Count('user'))
<QuerySet [{'interest': 5, 'user__count': 2}, {'interest': 6, 'user__count': 1}]>
# the interest(id=5) had been visited for 2 times, 
# and the interest(id=6) had only been visited for 1 time.

>>> Travel.objects.values('interest').annotate(Count('user', distinct=True)) 
<QuerySet [{'interest': 5, 'user__count': 1}, {'interest': 6, 'user__count': 1}]>
# the interest(id=5) had been visited by only one person (but this person had 
#  visited the interest for 2 times

আপনি এই বইটি ব্যবহার করে সমস্ত বই সন্ধান করতে এবং নাম অনুসারে তাদের গ্রুপ করতে পারেন:

Book.objects.values('name').annotate(Count('id')).order_by() # ensure you add the order_by()

আপনি এখানে কিছু চিট শীট দেখতে পারেন ।


-1

যদি আমি ভুল না করে থাকি তবে আপনি যা-যা-ক্যোয়ারী-সেট সেট করতে পারেন g group_by = [' ফিল্ড ']


8
এই ক্ষেত্রে, অন্তত জ্যাঙ্গো 1.6 নেই: 'QuerySet' অবজেক্ট কোন অ্যাট্রিবিউট 'group_by' হয়েছে
Facundo Olano

1
একটি যথাযথ ব্যবহার ক্যোরিসেট.উকেউরি.উইউআরপি_বি = [...] হতে পারে তবে এটি ক্যোয়ারির শব্দার্থবিজ্ঞান ভঙ্গ করবে এবং প্রত্যাশার মতো কাজ করবে না।
লুইস মাসুয়েলি

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