If I am not mistaken there is a field called deleted_at
If it is deleted, then there should be a date time Stamp.
If it is not deleted then is null
Maybe look for the entry that is <> Null and delete
If I am not mistaken there is a field called deleted_at
If it is deleted, then there should be a date time Stamp.
If it is not deleted then is null
Maybe look for the entry that is <> Null and delete
Thanks Gav, but the ones that I am targeting aren’t marked as deleted. Rather, their Topic has been deleted and then destroy_all’d.
I was playing around with this and i notice that part of your query was not returning the response you need.
SELECT topic_id from posts does not return an integer, but it returned a string

This might be the cause that your db still contains orphaned posts.
أعتقد أنك ترى مستكشف البيانات يقوم تلقائيًا بتحويل العدد الصحيح إلى عنوان URL، وهو ما يفعله عندما يكون التسمية topic_id.
عندما أقوم بتشغيل هذا الاستعلام في مستكشف البيانات، يتم التقاط جميع المشاركات التي أحاول تحديدها (أكثر من 5000):
SELECT id, topic_id
FROM posts
WHERE topic_id not in (select id from topics)
ORDER by id
من الواضح أنني أفعل شيئًا خاطئًا في بناء جملة Rails الخاصة بي حيث أن هذا ما أحصل عليه:
[1] pry(main)=> Target = Post.where('topic_id not in (select id from topics)')
=> []
هل يمكن لأي شخص أن يخبرني ما الذي أفعله بشكل خاطئ؟
حسنًا، بفضل @pfaffman، تمكنت من تحديد المشاركات ذات الصلة باستخدام هذا:
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
أحصل على هذا الناتج:
[1] pry(main)> Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”)
=> [#<Post:0x000055df30d4ee90 id: 150>,
#<Post:0x000055df2e538ff0 id: 51097>,
#<Post:0x000055df2e50ba28 id: 83>,
#<Post:0x000055df2e4ee8b0 id: 40636>,
#<Post:0x000055df2e4a92d8 id: 62562>,
#<Post:0x000055df2e4b7978 id: 13522>,
إلخ.
ومع ذلك، لا يمكنني معرفة كيفية تطبيق destroy_all على هذا التحديد.
قد يساعد هذا (لصالحي الخاص):
أي اقتراحات؟
أعتقد أن هذا سيفي بالغرض
posts=
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
posts.destroy_all
أو يمكنك إضافة .destroy_all إلى find_by_sql الخاص بك
لقد جربت ذلك. يبدو أن البيانات تُرجع كمصفوفة مع معرف منشور و ID (انظر Delete deleted-posts permanently in bulk? - #45 by nathank).
هذا هو الخطأ الذي أحصل عليه عندما أضيف .destroy_all أو أستخدم posts= الذي تقترحه:
[2] pry(main)> posts.destroy_all
NoMethodError: undefined methoddestroy_all' for #<Array:0x000055fe7bc7fc98> from (pry):3:inpry’
أوه. إذن ربما تحقق مما إذا كان
p=posts.first
هو معرف منشور. إذا كان الأمر كذلك، فيمكنك
x=Post.find(p)
x.destroy
ثم يمكنك المرور عبرها.
أعتقد أنك ستحتاج إلى تغليف استعلامك بشيء لجعله مصفوفة من المنشورات بدلاً من معرفات المنشورات.
شكراً جاي. هذه هي النتيجة التي أحصل عليها:
[3] pry(main)> p=
[3] pry(main)* posts.first
=> #<Post:0x0000563a24cab908 id: 150>
[4] pry(main)> x=Post.find(p)
ArgumentError: You are passing an instance of ActiveRecord::Base to find. Please pass the id of the object by calling .id.
from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.4.1/lib/active_record/relation/finder_methods.rb:467:in find_one’`
الآن، أخبرني عن هذه الأشياء المغلفة. هذا مزعج للغاية، لأنني أعرف أن أمر Rails الخاص بـ @Sam هنا يجب أن يعمل، ولكني أعتقد أن Rails قد تغير منذ ذلك الحين:
ماذا فعل ذلك؟ لا أستطيع أن أتخيل أن القضبان قد تغيرت.
هل يعطيك هذا المشاركات التي تريد حذفها؟
لقد قرأت في مكان ما على الإنترنت عند البحث عن تحويل مصفوفة Active Record إلى علاقة Active Record أن الأمور تغيرت بين Rails 3.x و Rails 4 وأن الصيغة تحتاج إلى أن تكون مختلفة، لكنها مرت فوق رأسي حقًا.
يبدو أن هذا قد التقط القليل عندما قمت بتشغيله لأول مرة، وقمت بتدميرها جميعًا. لكن لم يكن هناك الكثير. الآن لا يلتقط أي شيء على الإطلاق، بينما يلتقط SQL الآلاف عند تشغيله في مستكشف البيانات.
هذه منشورات يتيمة، حيث تم تدمير الموضوع بالكامل.
هل يمكنك استخدام each{} للتكرار على أعضاء تلك المصفوفة، واستدعاء destroy على كل منشور بشكل فردي؟
Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy }
حسنًا، لقد جربت ذلك. أولاً، لم يعجبه استعلام SQL المغلف بهذه الطريقة ولا الصيغة:
Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy_all }
SyntaxError: unexpected `in’, expecting ‘(’
…rom posts where topic_id not in (select id from topics)”)…
… ^~
SyntaxError: unexpected local variable or method, expecting end-of-input
…t in (select id from topics)”).each { |p| p.destroy_all }
لذلك، قمت بمحاولة أخرى غير تقليدية عن طريق تقسيمه:
posts=Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
posts.each do |p|
p.destroy
end
بدا أن هذا يعمل بشكل جيد، ولكن إضافة p.destroy يظهر هذا:
ActiveModel::MissingAttributeError: missing attribute: user_id
from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activemodel-6.1.4.1/lib/active_model/attribute.rb:222:in `value’
حاولت بضع طرق لإدخال ذلك هناك ولكنني استسلمت. @sam، هل يمكنك المساعدة؟
لقد حاولت حتى تحويل استعلام SQL إلى AR عبر scuttle.io كما هو موضح هنا:
Post.select([:id, :topic_id]).where(Topic.select(:id))
للأسف، أحصل على هذا الخطأ:
ArgumentError: Unsupported argument type: #Topic::ActiveRecord_Relation:0x000055c67a7131d0 (Topic::ActiveRecord_Relation)
عندما نسخت ولصقت هذا الجزء من رسالة سابقة، يبدو أن علامات الاقتباس تحولت إلى علامات اقتباس منحنية في مكان ما، أتوقع أن هذا هو الخطأ الحقيقي. آسف لذلك.
يوصف find_by_sql بأنه يعيد كائنًا بالقيم المحددة في استعلام SQL، مما يعني على الأرجح أنك تحصل على كائن Post يحتوي فقط على خاصية id، ويتم فقدان user_id وكل شيء آخر.
... find_by_sql("select * ... سيتعامل مع ذلك. من المحتمل أن يكون هناك مجموعة فرعية من القيم التي يمكنك تحديدها لتحقيق التدمير، بدلاً من تحديد كل شيء، ولكنني لا أعرف ما هي هذه المجموعة الفرعية.
لذا فالشيء بأكمله: (بدون علامات اقتباس منحنية هذه المرة…)
Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
شكرًا سيمون - لقد نجحت هذه الطريقة بشكل رائع. تم حذف جميع المشاركات اليتيمة وأتطلع إلى انخفاض حجم التحميلات الخاصة بي إلى ما يقرب من لا شيء خلال الـ 24 ساعة القادمة تقريبًا.
لاحقًا
وفعلوا ذلك! من 3.5 جيجابايت إلى 0.7 جيجابايت. رائع!!
ممتاز، يسعدني سماع أن ذلك نجح معك. لذا، لدمج الإجابات، يمكن استخدام ما يلي في وحدة تحكم Rails لحذف جميع المواضيع التي تم حذفها منذ أكثر من 90 يومًا، وتكرار ذلك حسب الضرورة إذا كان هناك أكثر من 1000 موضوع:
Topic.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all
بعد اكتمال ذلك، يمكن استخدام ما يلي لحذف جميع المشاركات التي تم يتّم يتيمتها من المواضيع المحذوفة:
Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
تجدر الإشارة إلى أن الأوامر المذكورة أعلاه لن تحذف المشاركات المحذوفة، بل المواضيع المحذوفة فقط والمشاركات اليتيمة الخاصة بها. لحذف المشاركات المحذوفة التي يزيد عمرها عن 90 يومًا أيضًا، استخدم ما يلي، وكرر حسب الضرورة:
Post.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all
ملاحظة جانبية: من باب الفضول، هل جربت destroy_all بدون limit(1000) وواجهت مشاكل، أم أنك لم تجربه بدون الحد؟
جربته بدون الحد وحدث شيء جنوني بعض الشيء - لكنني نسيت التفاصيل للأسف.
هل يمكننا وضع علامة على مشاركتك كحل أو استخدام هذا من المنشور الأصلي؟

لا تقلق. إذا لم تكن قد جربتها، لكنت أضفت ملاحظة بأن الحد قد لا يكون ضروريًا، ولكن بما أنك واجهت مشاكل، يمكنني تركها كما هي.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.