2016-04-13 9 views
0

私はPostgreSQLでRailsアプリケーションを持っています。効率的なスラックのようなサブドメイン名の提案を実装する

ユーザー入力が既に選択されている場合、特定のリソースの代替名を提案する方法を実装しようとしています。

私の参照が緩みです:

slack domain input

は、これを効率的に行うことができます任意の解決策はありますか?効率的にするために

I意味:クエリの一つだけかも小さなセットを使用しました。 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 ... in'クエリを使用します。それは正確に**一度**データベースに当たる。あなたが何を求めているのか分かりませんが、これを行うための既製品の宝石であれば、Stack Overflowの話題にはなりません。 – meagar

+0

@magagarもちろん、ソリューションは競合が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してください。同じ名前の2つのリクエストで競合状態の可能性のあるグリッチが1つある可能性がありますが、実際の作成が失敗した場合には常に謝罪することができますので問題は発生しません。

+0

面白い解決策。たぶん、私は 'NOT LIKE '(正規表現を使用)の代わりに' NOT RLIKE'を使って改良することができます。例えば、 '-'と' _'の両方を区切り文字として使用するなど、より多くの候補を除外します。 – ProGM

+0

確かに、これは単なる見出し/方向であり、完全な解決策ではありません。 – mudasobwa

+0

@SergioTulentsevああ、確かに: 'NOT'は余分です。 – mudasobwa

関連する問題