2016-04-13 25 views
0

我有一個Rails應用程序與PostgreSQL。實現一個有效的鬆弛狀子域名建議

我想實現一種方法來建議某個資源的替代名稱,如果用戶輸入已被選中。

我參考鬆弛:

slack domain input

是否有可能有效地做到這一點的任何解決方案?

爲了有效地我的意思是:用只有一個或也小組查詢的。 A 純粹的SQL解決方案會很好,但。

我最初的實現是這樣的:

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),它也不會無限縮放。

您是否知道改進此方法,因此可以調整大量衝突並且不使用幻數?

+0

您的方法在查詢中使用了一個「where ...」。它完全符合**一次**。我不確定你在問什麼,但是如果這是一個現成的Gem來做這件事,那麼Stack Overflow就是一個關鍵問題。 – meagar

+0

@meagar當然,但解決方案只有在衝突小於100的情況下才有效。即使我產生了更多的候選人,它也不會無限地縮放。我相信有更好的方法。 :) – ProGM

回答

2

我會去的逆轉方法:查詢使用LIKE現有記錄的數據庫,然後生成建議跳過已經採取:

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 

做一個generate_candidates_using_a_certain_strategy接收已經採取字數組被跳過。對於兩次請求採用相同名稱的競爭條件,可能會出現一個可能的小故障,但我不認爲這可能會導致任何問題,因爲當實際創建失敗時,您總是可以自由道歉。

+0

有趣的解決方案。也許我可以使用'NOT RLIKE'而不是'NOT LIKE'(使用正則表達式)來改進它,以便匹配更多的候選項以排除(例如,允許'-'和'_'作爲分隔符)。 – ProGM

+0

當然,這只是一個標題/方向,而不是一個完整的解決方案。 – mudasobwa

+0

@SergioTulentsev哦,呃,確實:)'NOT'是多餘的。 – mudasobwa