Ruby on rails 实现一个有效的类似slack的子域名建议
我有一个带有PostgreSQL的Rails应用程序 我正在尝试实现一种方法,如果已经选择了用户输入,则可以为某个资源建议其他名称 我的参考是: 有什么解决方案可以有效地做到这一点吗? 为了提高效率,我的意思是:只使用一个或同时使用一组小的查询。不过,一个纯SQL解决方案将非常好 我最初的实现如下所示:Ruby on rails 实现一个有效的类似slack的子域名建议,ruby-on-rails,ruby,postgresql,Ruby On Rails,Ruby,Postgresql,我有一个带有PostgreSQL的Rails应用程序 我正在尝试实现一种方法,如果已经选择了用户输入,则可以为某个资源建议其他名称 我的参考是: 有什么解决方案可以有效地做到这一点吗? 为了提高效率,我的意思是:只使用一个或同时使用一组小的查询。不过,一个纯SQL解决方案将非常好 我最初的实现如下所示: def generate_alternative_names(model, column_name, count) words = model[column_name].split(/[,
def generate_alternative_names(model, column_name, count)
words = model[column_name].split(/[,\s\-_]+/).reject(&:blank?)
candidates = 100.times.map! { |i| generate_candidates_using_a_certain_strategy(i, words) }
already_used = model.class.where(column_name => candidates).pluck(column_name)
(candidates - already_used).first(count)
end
# Usage example:
model = Domain.new
model.name = 'hello-world'
generate_alternative_names(model, :name, 5)
# => ["hello_world", "hello-world2", "world_hello", ...]
它生成100个候选项,然后检查数据库中是否有匹配项,并将其从候选项列表中删除。最后,它返回提取的第一个count
值
此方法是一种尽力而为的实现,因为它适用于少量冲突(在我的例子中为100个冲突)的建议集
即使我增加这个神奇的数字(100),它也不会无限扩展
您知道一种改进方法吗,这样它可以扩展到大量冲突,而不使用幻数?我会使用相反的方法:使用查询数据库中的现有记录,然后生成跳过已采取的建议:
def alternatives(model, column, word, count)
taken = model.class.where("#{column} LIKE '%#{word}%'").pluck(column)
count.times.map! do |i|
generate_candidates_using_a_certain_strategy(i, taken)
end
end
使用某种策略生成候选词,以接收要跳过的已取单词数组。两个同名请求可能存在一个可能的争用条件故障,但我认为这不会导致任何问题,因为当实际创建失败时,您可以随时道歉。我会采用相反的方法:使用查询数据库中的现有记录,然后生成跳过已采取的建议:
def alternatives(model, column, word, count)
taken = model.class.where("#{column} LIKE '%#{word}%'").pluck(column)
count.times.map! do |i|
generate_candidates_using_a_certain_strategy(i, taken)
end
end
使用某种策略生成候选词,以接收要跳过的已取单词数组。两个同名请求的竞态条件可能存在一个问题,但我认为这不会导致任何问题,因为当实际创建失败时,您可以随时道歉。您的方法使用单个
其中。。。在
查询中。它只命中数据库一次。我不知道你要的是什么,但如果这是一个现成的Gem来做这件事,那就和堆栈溢出无关了。@meagar当然,但解决方案只有在冲突小于100时才有效。即使我产生了更多的候选人,它也不会无限期地扩展。我相信有更好的方法。:)您的方法使用单个,其中。。。在
查询中。它只命中数据库一次。我不知道你要的是什么,但如果这是一个现成的Gem来做这件事,那就和堆栈溢出无关了。@meagar当然,但解决方案只有在冲突小于100时才有效。即使我产生了更多的候选人,它也不会无限期地扩展。我相信有更好的方法。:)有趣的解决方案。也许我可以用-NOT-RLIKE
而不是NOT-LIKE
(使用regexp)来改进它,以匹配更多要排除的候选项(例如,同时允许-
和\uuu
作为分隔符)。当然,这只是一个标题/方向,不是一个完整的解决方案。@SergioTulentsev噢,呃,的确:)不
是多余的。@ProGM请看一个更新,我把事情搞砸了,像
是要用的,不是不像
,谢谢Sergio的敏锐眼光。耶,谢谢@SergioTulentsev,我也没注意到。:)有趣的解决方案。也许我可以用-NOT-RLIKE
而不是NOT-LIKE
(使用regexp)来改进它,以匹配更多要排除的候选项(例如,同时允许-
和\uuu
作为分隔符)。当然,这只是一个标题/方向,不是一个完整的解决方案。@SergioTulentsev噢,呃,的确:)不
是多余的。@ProGM请看一个更新,我把事情搞砸了,像
是要用的,不是不像
,谢谢Sergio的敏锐眼光。耶,谢谢@SergioTulentsev,我也没注意到。:)