1

今、私は要件を持っています。

ユーザーが存在名を入力するとき、ユーザーに使用可能な名前をすばやく表示する必要があります。そしてフロントエンドでは問題ありません。しかし、バックエンドでは、シャープなコードをコーディングする方法は?

この関数は、ユーザーが名前「Java」を使用して電子メールアカウントを登録する場合、重複が見つかった場合に、「Java01」、「Java001」、「Java002」などの利用可能な名前の提案をユーザーに提供するようなものです。

現在、私の考えは次のとおりです。

ユーザー入力名は「Name01」です。
まず、「JPQL(JPA)」を使用して、名前が存在することを検証します。
存在する場合は、次のようなSQLを作成しますSelect name from table a where a.name like 'Name01%'
。次に、存在名リストを取得します。{'Name012','Name014','Name015'...}
したがって、「Name01」を使用して次のような推測リストを一般{'Name010','Name011','Name012','Name013','Name014',...}
化します。次に、推測リストを使用して存在名リストを比較し、10サイズのリストを返します(dbには存在しないはずです。ユーザーはそれらの1つを使用して保存できます) 2番目の検証を回避するために迅速に要求します。)のように:{'Name010','Name011','Name013','Name016',...}
しかし、推測がデータベース内のすべての存在をリストしている場合。'Name0%'でdbを検索し、再帰を実行する必要があります。

それはとても非効率的なようです。推測リストを一般化する方法と、比較の頻度を減らすために比較する方法がわかり
ません。 誰もが良い解決策を持っていますか?

ヒント:JSF + EJB + JPA(Eclipse Link 1.0)DB2を使用します。名前の最大長は10で、文字のみを含めることができます。

4

5 に答える 5

2

正直なところ...非常にインテリジェントなWebアプリが実際にricky01やricky011などを提案しているのは非常に苛立たしいことです。

私たちはまだ人間であり、ニックネームを思いついた理由は、IDを覚える必要がないようにするためです。これは、多かれ少なかれ、%01のような提案を提供するシステムで最終的に起こることです。

ユーザーが自分の電子メールアドレスのようなはるかに高い可視性を持つもののためにすでに選択したユーザー名を提案するだけでよいのではないでしょうか?

電子メールは定義上一意であり、グーグルのように遊ぶことができます。「email@domain.comと入力した場合」、最初に電子メールが彼の有効なユーザー名であるかどうかを確認します。

私が言っていることは、あなたがはるかにユーザーフレンドリーなシステムになってしまうということだと思います。

于 2012-07-27T14:06:21.803 に答える
2

この状況で使用する効率的なデータ構造はTrie(プレフィックスツリー)です。

アプリケーションの一部として、TrieすべてのNameを使用してを生成する必要があります。このデータ構造を使用して、ユーザープロンプトを生成できます。このデータ構造の利点は、時間計算量をに減らすことO(n)です。

例:name0、name10、name45は、次のノードを持つTrieを生成します

root node - "n"
node Level 1 - "a"
node Level 2 = "m"
node Level 3 = "e"
node Level 4 = "0" , "1" , "4"
node Level 4 = "0" , "5"
于 2012-07-30T11:00:42.543 に答える
0

私があなたを正しく理解している場合、あなたはいくつかのステップを持っています:1)ユーザーは彼らの好みのuserNameを入力します(制限なしのフリーテキストエントリ、おそらくいくつかのルール)2)あなたは上からユーザーエントリを検証し、それがユニークであるか現在のユーザーである場合はそれを受け入れますいくつかの選択肢(この時点でユーザーのフリーテキスト入力を無効にしますか?)3)ステップ2からのユーザー選択を受け入れます)(すでに一意であると想定しているため、さらに検証する必要はありませんか?)

何かを想定し、検証なしでユーザーデータを受け入れることは決して良い考えではありません。このため、ステップ3)はステップ2)と同じ検証を実行する必要があります。つまり、ステップ3)はなく、繰り返されるだけです。ステップ2)。

それはステップ2)の機能を残します

ユーザーストア(DB)にクエリを実行して、エントリが一意であるかどうかを確認します。

a)それはユニークです-新しいエントリを作成し、ユーザーに通知します

b)すでに存在している-ユーザーストアにLIKEエントリを照会します。通常は、userEnteredStringFromStep1+someWayOfMakingYourStringUniqueになります。最も一般的には、someWayOfMakingYourStringUniqueは単なる数値です。したがって、ユーザーストアにLIKE'userEnteredStringFromStep1%'を照会し、上記の結果に存在しない新しいuserEnteredStringFromStep1+someWayOfMakingYourStringUniqueの組み合わせを生成する必要があります。

于 2012-08-01T09:43:10.613 に答える
0

おそらく、最初に生成ルールを事前に定義できます。

たとえば、ユーザーの入力が存在する場合、この入力をランダムに生成された文字と数字と連結して10サイズの提案リストを作成し、1つのクエリを使用してそれらが使用可能であることを確認します。このリストが実際に使用できることはめったにないため、ほとんどの場合成功しますが、そうでない場合は、リストを再度生成するだけです。

userInput = "java"
generate list = {"java01","java02","java03",...}
select count(*) into existence from table a where a.name in (list)
if existence >0 then regenerate else return list

したがって、最初にルールを定義して提案リストのルールを生成し、このアルゴリズムを初めてほぼ成功させ、提案をユーザーの要望に近づけます。

于 2012-07-31T09:20:08.113 に答える
0

Byterが指摘しているように、aTrieは使用するのに最適なオブジェクトタイプです。ただし、使いやすいJava実装を見つけるのは難しいです。2番目に良いオプションを取り、標準クラスに固執して、ハックのためにこれはどうですか?(ユーザーがUTF-8を使用していることを前提としています)

import com.google.common.collect.*;
import java.util.*;

public class Subsearch {

    private static final List<String> EXAMPLE_RESULTS = Lists.newArrayList("Name010", "Name011", "Name012", "Name013", "Name014", "Name100");

    public static void main(String[] args) {
        // EXAMPLE_RESULTS is from the DB lookup, also retain the original user string
        // exit if the user didn't add one character to the end of the original string
        SortedSet<String> sorted = Sets.newTreeSet(EXAMPLE_RESULTS);
        String userInput = "Name0";
        String upper = userInput + "\uFFFF";        
        SortedSet<String> trimmed = sorted.subSet(userInput, upper);
        // save "trimmed" and userInput for the next iteration
        // no need to store EXAMPLE_RESULTS anymore
        System.out.println(trimmed);
    }
}

私はこれを次のように警告します:ルックアップコードを実際に最適化する必要があることを確認してください。DBがヒットに悩まされていない場合は、この余分な複雑さの層を導入しないでください(維持するための余分なコードと同時実行性の問題の可能性の増加)。インデックスを作成した場合@Column、DBが実際にTrie内部で使用している可能性があります。

ちなみに、あなたはあなたのコラムにインデックスを付けましたね?そうでない場合は、次のHibernate固有のアノテーションをフィールドに追加することでこれを行うことができます

@org.hibernate.annotations.Index
@Column
String name;

(DBスキーマを再構築することを忘れないでください)またはネイティブクエリを発行します。

于 2012-07-31T11:42:47.647 に答える