Firebase
リアルタイムデータベースを使用してAndroidアプリケーションを作成しています。新しいユーザーがアプリに登録すると、そのユーザーのデータはFirebaseデータベースに保存されます。
ユーザーは登録するために次の詳細を提供する必要があります。
新しいユーザーが登録しようとするたびに、各ユーザーのユーザー名が一意であることを確認する必要があるため、ユーザーが入力したusername
がデータベースに既に存在するかどうかを確認します。
これを行うために、次のメソッドを作成しました。
private boolean usernameExists(String username) {
DatabaseReference fdbRefer = FirebaseDatabase.getInstance().getReference("Users/"+username);
return (fdbRefer != null);
}
このメソッドの背後にある私のロジックは、getReference
メソッドが指定されたパスへの参照を見つけられない場合、nullを返すので、fdbRefer
がnull
であるかどうかを返します。 fdbRefer
がnull
である場合、username
がデータベースに存在しないことを意味します。
このメソッドの問題は、入力されたtrue
がデータベースに存在するかどうかにかかわらず、常にusername
を返すことです。 fdbRefer
がnull
になることはないと信じるようになりました。
これは私の質問に私をもたらします...
getReference
データベースで指定されたパスが見つからないときにfirebase
メソッドが返すもの、およびusername
がデータベースに既に存在するかどうかを確認する正しい方法は何ですか?
ユーザーの存在を確認するには、次のコードを使用してください。
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userNameRef = rootRef.child("Users").child("Nick123");
ValueEventListener eventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(!dataSnapshot.exists()) {
//create new user
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
}
};
userNameRef.addListenerForSingleValueEvent(eventListener);
クエリを使用して、次のような同じことを実現することもできます。
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("Users").orderByChild("userName").equalTo("Nick123");
query.addValueEventListener(/* ... */);
これは、Users
ノード全体をループする別のアプローチですが、単一のユーザーへの直接参照を使用するだけではありません。このオプションは、ユーザー名の代わりにuid
を一意の識別子として使用している場合に使用する可能性が高くなります(現在のように)。したがって、データベース構造が次のようになる場合:
Firebase-root
|
--- Users
|
--- uid
|
--- userName: "Test User"
|
--- emailAddress: "[email protected]"
2番目のソリューションが推奨されます。
一意のユーザー名のみを保持できるuserNames
という名前の別のノードを作成する必要がある別のソリューションもあります。以下の対応するセキュリティルールも参照してください。
"Users": {
"$uid": {
".write": "auth !== null && auth.uid === $uid",
".read": "auth !== null && auth.provider === 'password'",
"userName": {
".validate": "
!root.child('userNames').child(newData.val()).exists() ||
root.child('userNames').child(newData.val()).val() == $uid"
}
}
}
ただし、この場合、ユーザー名はすでにノードの名前であるため、最初のユーザー名を使用することをお勧めします。
これを試して:
_DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Users");
ref.orderByChild("username").equalTo(Nick123).addValueEventListener(new ValueEventListener(){
@Override
public void onDataChange(DataSnapshot dataSnapshot){
if(dataSnapshot.exist() {
//username exist
}
}
_
値がある場合は、orderbychild
とequalto
を使用して値を確認する必要があります。 orderbychild
とequalto
を使用しない場合、username
子ノードが存在するかどうかを確認し、値を気にしません。
このorderByChild("username").equalTo(Nick123)
は次のようなものです:
_WHERE username=Nick123
_
このように確認してください...
fdbRefer.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exist() {
//username exist
}
else {
//username doesn't exist
}
}
});
私にぴったり
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference
.child(getString(R.string.dbname_users))
.orderByChild("username")
.equalTo(username);
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.getChildrenCount()>0) {
//username found
}else{
// username not found
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
参照の存在を確認する代わりに、orderByクエリを使用してユーザー名が既に存在するかどうかを確認できます
orderByChild( 'username')。equalTo(username)クエリは、データが既に存在する場合はデータを返しますが、それ以外の場合はnullを返します。
あなたはすでにあなたの問題の解決策を持っているので、私はあなたのコードが機能しなかった理由を説明しようとします。
_DatabaseReference fdbRefer = FirebaseDatabase.getInstance().getReference("Users/"+username);
_
「Users /」+ usernameがデータベースに存在しない場合、上記のステートメントでfdbRefer
はnullになると考えているかもしれません。
しかし、実際には、このステートメントはgetReference()
の指定されたフィールドへのパスのみを保存します。 _fdbRef!=null
_をチェックすると、fdbRefer
は 'https://.firebase.com/Users/Nick123のような値を保持するため、常にtrueです。