حذف جميع المستخدمين غير الموجودين في مجموعة معينة

كجزء من ترحيل أو دمج بين منتديات Discourse، أحاول حذف جميع المستخدمين غير المنتمين إلى مجموعة محددة.

جربت الأمر التالي في وحدة تحكم Rails:
User.joins(:group_users).where.not(group_users:{group_id:135}).destroy_all

لسوء الحظ، أدى ذلك إلى حذف جميع المستخدمين، وهو ما كان مزعجًا بعض الشيء!

وجدت طريقة معقدة للقيام بذلك باستخدام الواجهة الرسومية وبعض كود Rails غير أنيق، لكن هل توجد طريقة أسهل؟ ربما أخطأت ببساطة في الصيغة.

إليك ما جربته، بعد تعب كبير لإنشاء مجموعة ضخمة تضم المستخدمين المراد حذفهم (حوالي 6000 مستخدم) عبر الواجهة الرسومية:

rails c
 target_group = Group.find_by_name("nz-not")
 users = User.joins(:group_users).where(group_users:{group_id: target_group.id})
 users.each do |u|
 u.destroy
 end
exit

أيضًا، ما الفرق بين استخدام destroy و UserDestroyer؟ هل يجب أن أستخدم الأخير؟

أجيب على سؤالي بنفسي بعد أن تعلمت بعض الدروس.

  1. نعم، استخدم UserDestroyer وإلا ستصبح قاعدة بياناتك مليئة بالسجلات اليتيمة.
  2. قد تحتاج إلى استخدام حيلة ذكية في كيفية جمع المستخدمين غير المرغوب فيهم. استخدمت استعلام مستكشف البيانات هذا للحصول على قائمة بهم، ثم أضفتهم جماعيًا إلى مجموعة تسمى unwanted
WITH included_users AS (
SELECT
gu.user_id
FROM group_users gu
JOIN groups g
ON g.id = gu.group_id
WHERE g.name = :included_group
),

excluded_users AS (
SELECT
gu.user_id
FROM group_users gu
JOIN groups g
ON g.id = gu.group_id
WHERE g.name = :excluded_group
)

SELECT 
     u.id AS user_id, u.username
FROM users as u
WHERE u.id in (SELECT user_id FROM included_users)
AND u.id NOT IN (SELECT user_id FROM excluded_users)
GROUP by u.id

كيفية تدمير عدد كبير من المستخدمين:

ادخل إلى تطبيق Discourse (./launcher enter app، وما إلى ذلك) وقم بتشغيل الأوامر التالية:

rails c
target_group = Group.find_by_name("unwanted")
users = User.joins(:group_users).where(group_users:{group_id: target_group.id})
users.each do |u|
 u.admin = false
 u.moderator = false
 u.save
 UserDestroyer.new(Discourse.system_user).destroy(u, delete_posts: true)
end
Exit

ليست العملية سريعة. بالنسبة لـ 6000 مستخدم، استغرقت ساعتين.

إعجاب واحد (1)