জ্যাঙ্গোর সাথে কীভাবে 'বাল্ক আপডেট' করবেন?


163

আমি জ্যাঙ্গোর সাথে একটি টেবিল আপডেট করতে চাই - কাঁচা এসকিউএলে এরকম কিছু:

update tbl_name set name = 'foo' where name = 'bar'

আমার প্রথম ফলাফলটি এরকম কিছু - তবে এটি বাজে, তাই না?

list = ModelClass.objects.filter(name = 'bar')
for obj in list:
    obj.name = 'foo'
    obj.save()

আরও কি মার্জিত উপায় আছে?


1
আপনি ব্যাচ সন্নিবেশ খুঁজছেন হতে পারে। স্ট্যাকওভারফ্লো
প্রমোদ

আমি নতুন ডেটা toোকাতে পছন্দ করি না - কেবলমাত্র বিদ্যমান আপডেট করুন।
থমাস শোয়ারজল

3
সাহায্যের সাহায্যে সিলেক্ট_ফরম্যাট আপ? docs.djangoproject.com/en/dev/ref/models/querysets/…
জুরে সি

ModelClassপদ্ধতির সম্পর্কে বাজে কি না ? তারপর যেমন জ্যাঙ্গো ফীড stackoverflow.com/questions/16853649/...
সিরো Santilli郝海东冠状病六四事件法轮功

উত্তর:


256

হালনাগাদ:

জ্যাঙ্গো ২.২ সংস্করণে এখন একটি বাল্ক_আপডেট রয়েছে

পুরানো উত্তর:

নিম্নলিখিত জাজানো ডকুমেন্টেশন বিভাগটি পড়ুন

একসাথে একাধিক অবজেক্ট আপডেট করা হচ্ছে

সংক্ষেপে আপনি ব্যবহার করতে সক্ষম হবেন:

ModelClass.objects.filter(name='bar').update(name="foo")

Fসারি বাড়ানোর মতো জিনিসগুলি করতে আপনি অবজেক্টগুলিও ব্যবহার করতে পারেন :

from django.db.models import F
Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

ডকুমেন্টেশন দেখুন ।

তবে, নোট করুন:

  • এটি ModelClass.saveপদ্ধতি ব্যবহার করবে না (সুতরাং আপনার ভিতরে যদি কিছু যুক্তি থাকে তবে এটি ট্রিগার হবে না)।
  • কোনও জ্যাঙ্গো সংকেত নির্গত হবে না।
  • আপনি .update()একটি কাটা কোয়েরীসেটে একটি সম্পাদন করতে পারবেন না , এটি অবশ্যই একটি মূল ক্যোরিসেটে থাকা উচিত যাতে আপনার পদ্ধতি .filter()এবং .exclude()পদ্ধতিগুলির উপর ঝুঁকতে হবে ।

27
এছাড়াও মনে রাখবেন ব্যবহার করছেন না ফলত save(), DateTimeFieldসঙ্গে ক্ষেত্র auto_now=True( "রুপান্তরিত" কলাম) আপডেট করা হবে না।
আর্থার

3
তবে ModelClass.objects.filter(name = 'bar').update(name="foo")বাল্ক আপডেটের উদ্দেশ্য পূরণ করে না, যদি আমার কাছে বিভিন্ন আইডির জন্য আলাদা আলাদা ডেটা থাকে তবে লুপটি ব্যবহার না করে আমি কীভাবে এটি করতে পারি?
শশাঙ্ক

@ শিহোন আমি আপনাকে সঠিকভাবে পেয়েছি কিনা তা নিশ্চিত নই তবে আমি উত্তরে উদাহরণ যোগ করেছি।
জেবি।

@ শশাঙ্ক কি এখনও আপনার মামলার কোনও সমাধান খুঁজে পেয়েছেন? আমারও একই অবস্থা হচ্ছে।
সৌরভ প্রেম

এফ অবজেক্টগুলি। আপডেট পদ্ধতিতে বিভিন্ন মডেলের রেফারেন্স হিসাবে ব্যবহার করা যায় না ... উদাহরণস্বরূপ আপনি ব্যবহার করতে পারবেন না Entry.objects.all().update(title=F('blog__title'))। দস্তাবেজের এ সম্পর্কে একটি ছোট্ট উল্লেখ রয়েছে। আপনি যদি নিজের এন্ট্রিগুলি আপডেট করতে অন্য কোনও মডেল থেকে ডেটা টানতে চান তবে আপনাকে লুপের জন্য চালাতে হবে
sean.hudson

31

গিটহাব-এ এখানেdjango-bulk-update পাওয়া ব্যবহার বিবেচনা করুন ।

ইনস্টল করুন: pip install django-bulk-update

প্রয়োগ করুন: (প্রকল্পগুলি ReadMe ফাইল থেকে সরাসরি নেওয়া কোড)

from bulk_update.helper import bulk_update

random_names = ['Walter', 'The Dude', 'Donny', 'Jesus']
people = Person.objects.all()

for person in people:
    r = random.randrange(4)
    person.name = random_names[r]

bulk_update(people)  # updates all columns using the default db

আপডেট: মার্ক যেমন মন্তব্যগুলিতে উল্লেখ করেছেন এটি একবারে কয়েক হাজার সারি আপডেট করার জন্য উপযুক্ত নয়। যদিও এটি ছোট ব্যাচ 10 এর থেকে 100 এর জন্য উপযুক্ত। আপনার জন্য উপযুক্ত ব্যাচের আকারটি আপনার সিপিইউ এবং কোয়েরি জটিলতার উপর নির্ভর করে। এই সরঞ্জামটি ডাম্প ট্রাকের চেয়ে চাকা ব্যারোর মতো।


16
আমি জাঙ্গো-বাল্ক-আপডেট চেষ্টা করেছি এবং আমি ব্যক্তিগতভাবে এটি ব্যবহার করে নিরুৎসাহিত করেছি। এটি অভ্যন্তরীণভাবে যা করে তা হ'ল একক এসকিউএল স্টেটমেন্ট তৈরি করা যা দেখতে এটির মতো দেখাচ্ছে: আপডেট করুন "টেবিল" সেট "ক্ষেত্র" = CASE "আইডি" যখন% s ত্রয়োদশ% যখন তৃতীয়% [...] আইডি যেখানে ( % s,% s, [...]);। এটি কয়েকটি সারিগুলির জন্য একদম ঠিক আছে (যখন বাল্ক আপডেটের প্রয়োজন হয় না), তবে 10,000 সহ কোয়েরিটি এত জটিল, যে পোস্টটি ডিস্কে লেখার সময় সাশ্রয়ের চেয়ে 100% কোরিয়াকে বোঝার জন্য বেশি সময় ব্যয় করে ।
মার্ক গার্সিয়া

1
পছন্দ করুন আমি অনেক বিকাশকারী তাদের প্রভাবগুলি না জেনে বাহ্যিক গ্রন্থাগারগুলি ব্যবহার করে দেখতে পেয়েছি
দেজেল

3
@ মার্কগার্সিয়া আমি একমত নই যে বাল্ক আপডেট মূল্যবান নয় এবং কেবলমাত্র হাজারো আপডেটের প্রয়োজন হলে কেবল সত্যই প্রয়োজন। একবারে 10,000 সারি করার জন্য এটি ব্যবহার করা আপনার উল্লেখযোগ্য কারণগুলির জন্য উপযুক্ত নয় তবে এটি একবারে 50 টি সারি আপডেট করতে ব্যবহার করা 50 টি পৃথক আপডেট অনুরোধের সাথে ডিবি হিট করার চেয়ে অনেক বেশি কার্যকর।
এভেরেস্ট

3
আমি যে সেরা সমাধানগুলি পেয়েছি তা হ'ল: ক) @ ট্রানজেকশন.টমিক ডিকোরেটর ব্যবহার করুন, যা একক লেনদেন ব্যবহার করে কর্মক্ষমতা উন্নত করে, বা খ) অস্থায়ী টেবিলটিতে একটি বাল্ক সন্নিবেশ তৈরি করে এবং তারপরে অস্থায়ী টেবিল থেকে মূল একটিতে একটি আপডেট।
মার্ক গার্সিয়া

1
আমি জানি এটি একটি পুরানো থ্রেড, তবে বাস্তবে কেএসই / যেখানে একমাত্র উপায় নয়। পোস্টগ্রেএসকিউএল-এর জন্য অন্যান্য পন্থা রয়েছে তবে তারা ডিবি নির্দিষ্ট যেমন স্ট্যাকওভারফ্লো.com/a/18799497 তবে এএনএসআই এসকিউএলে এটি সম্ভব কিনা তা আমি নিশ্চিত নই
ইলিয়ান ইলিয়েভ

21

জ্যাঙ্গো ২.২ সংস্করণে এখন একটি bulk_updateপদ্ধতি রয়েছে ( রিলিজ নোটগুলি )।

https://docs.djangoproject.com/en/stable/ref/models/querysets/#bulk-update

উদাহরণ:

# get a pk: record dictionary of existing records
updates = YourModel.objects.filter(...).in_bulk()
....
# do something with the updates dict
....
if hasattr(YourModel.objects, 'bulk_update') and updates:
    # Use the new method
    YourModel.objects.bulk_update(updates.values(), [list the fields to update], batch_size=100)
else:
    # The old & slow way
    with transaction.atomic():
        for obj in updates.values():
            obj.save(update_fields=[list the fields to update])

1
প্রকৃতপক্ষে, এটি ২.২
বেনোইট ব্লাঞ্চন

8

আপনি যদি সারিগুলির সংগ্রহে একই মানটি সেট করতে চান তবে আপনি একটি ক্যোয়ারীতে সমস্ত সারি আপডেট করতে যে কোনও প্রশ্নের সাথে মিলিয়ে আপডেট () পদ্ধতিটি ব্যবহার করতে পারেন:

some_list = ModelClass.objects.filter(some condition).values('id')
ModelClass.objects.filter(pk__in=some_list).update(foo=bar)

আপনি যদি কিছু শর্তের উপর নির্ভর করে বিভিন্ন মান সহ সারিগুলির সংগ্রহ আপডেট করতে চান তবে আপনি সেরা ক্ষেত্রে মান অনুসারে আপডেটগুলি ব্যাচ করতে পারেন। ধরা যাক আপনার 1000 টি সারি রয়েছে যেখানে আপনি এক্স মানগুলির মধ্যে একটিতে কলাম সেট করতে চান, তারপরে আপনি ব্যাচগুলি আগেই প্রস্তুত করতে পারেন এবং কেবল এক্স আপডেট-কোয়েরি চালাতে পারেন (প্রত্যেকটি মূলত উপরে প্রথম উদাহরণের ফর্ম রয়েছে) + প্রাথমিক নির্বাচন করুন -প্রশ্ন.

যদি প্রতিটি সারিতে একটি স্বতন্ত্র মান প্রয়োজন হয় তবে প্রতি আপডেটের জন্য একটি ক্যোয়ারী এড়ানোর কোনও উপায় নেই। এই অন্যান্য ক্ষেত্রে যদি আপনার দক্ষতার প্রয়োজন হয় তবে সম্ভবত অন্যান্য আর্কিটেকচারগুলিতে সিকিউআরএস / ইভেন্ট সোর্সিংয়ের দিকে নজর দিন।


1

আইটি রিটার্ন অবজেক্টের সংখ্যা সারণিতে আপডেট করা হয়।

update_counts = ModelClass.objects.filter(name='bar').update(name="foo")

বাল্ক আপডেট এবং তৈরি সম্পর্কে আরও তথ্য পেতে আপনি এই লিঙ্কটি উল্লেখ করতে পারেন। বাল্ক আপডেট এবং তৈরি করুন

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