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.
我认为您看到的是 Data Explorer 自动将整数转换为 URL,当标签为 topic_id 时,它会这样做。
当我在 Data Explorer 中运行此查询时,我尝试识别的所有帖子都被捕获(远超 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>,
etc
但是,我不知道如何将 destroy_all 应用于此选择。
这可能有助于(对我自己而言):
有什么建议吗?
我认为这会起作用
posts=
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
posts.destroy_all
或者你也可以在 find_by_sql 中添加 .destroy_all
我已经试过了。数据似乎被返回为一个数组,其中包含一些帖子标识符和 ID(参见 https://meta.discourse.org/t/delete-deleted-posts-permanently-in-bulk/203289/45)。
当我添加 .destroy_all 或使用你建议的 posts= 时,我收到的错误是:
[2] pry(main)> posts.destroy_all
NoMethodError: undefined methoddestroy_all' for #<Array:0x000055fe7bc7fc98> from (pry):3:inpry’
哦。那么也许可以看看
p=posts.first
是否是 post_id。如果是这样,那么你就可以
x=Post.find(p)
x.destroy
然后你可以循环遍历它们。
我认为你需要将你的查询包装在某个东西中,使其成为一个帖子的数组而不是 post ids。
谢谢 Jay。我得到的是:
[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 tofind. 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’
现在,告诉我关于这些包装的东西。这太烦人了,因为我知道 @Sam 的这个 rails 命令应该可以工作,但我认为 Rails 已经和那时不一样了:
那做了什么?我无法想象 Rails 发生了变化。
这能得到你想删除的帖子吗?
我在网上搜索将 Active Record 数组转换为 Active Record Relation 时读到,Rails 3.x 和 Rails 4 之间的语法有所不同,但当时我没太理解。
我第一次运行它时,它似乎找到了一些帖子,并且我 duly destroy_all 了它们。但数量不多。现在一个也找不到,而当我在 Data Explorer 中运行 SQL 时,却能找到数千条。
这些是孤立的帖子,它们的 Topic 已经被 Destroy_all 了。
您可以使用 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,你能帮忙吗?
我甚至尝试按照这个方法,通过 scuttle.io 将 SQL 转换为 AR:
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 }
太好了,很高兴听到这能帮到你。为了合并这些答案,你可以在 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
附言 顺便问一下,你是否尝试过不带 limit(1000) 的 destroy_all 并遇到了问题,还是你根本没有尝试过不带限制的命令?
我尝试过不带限制的它,结果有点失控——但抱歉,我记不清具体细节了。
我们可以将你的帖子标记为解决方案,或者使用 OP 的内容吗?

没关系。如果你没试过,我会加个注释说这个限制可能不是必需的,但既然你遇到了问题,我就保持原样。
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.