次のFirebaseデータベース構造があります。 uIds
は_List<String>
_のタイプです。 uIds
の下に、インデックスを増やして別のuIdを追加しようとしています。 setValue()
およびupdateChildren()
は、既存のデータを取得する必要があり、Push()
は、増分インデックスではなく、ランダムに生成された文字列をキーとしてアイテムを追加します。既存のデータを取得する必要のない簡単な方法はありますか?ありがとう!
_ "requests" : {
"request001" : {
"interests" : [ "x" ],
"live" : true,
"uIds" : [ "user1" ] // <---- from this
},
"request002" : {
"interests" : [ "y" ],
"live" : true,
"uIds" : [ "user2" ]
}
}
_
編集:
不明瞭でごめんなさい。明確にするために詳しく説明します。上記のデータベースがあり、次のように更新したいとします。
_ "requests" : {
"-KSVYZwUQPfyosiyRVdr" : {
"interests" : [ "x" ],
"live" : true,
"uIds" : [ "user1", "user2" ] // <--- to this
},
"-KSl1L60g0tW5voyv0VU" : {
"interests" : [ "y" ],
"live" : true,
"uIds" : [ "user2" ]
}
}
_
ishmaelMakitlaの提案mDatabase.child("requests").child("request001").setValue(newRequest)
は、「request001」を「newRequest」で上書きします。したがって、「request001」の既存のデータを取得し、「user2」をリストuIds
に追加する必要があります。次のようなものになります。
_mDatabase.child("requests").child("request001").addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Request newRequest = dataSnapshot.getValue(Request.class);
newRequest.uIds.add("user2");
mDatabase.child("requests").child("request001").setValue(newRequest);
}
@Override
public void onCancelled(DatabaseError databaseError) {}
});
_
しかし、私がやろうとしているのはリストuIds
に1つのアイテムを追加するだけなので、このプロセスが必要かどうか疑問に思っています。
スケーリングするデータの作成に関するFirebaseのドキュメント では、異なるデータ構造を使用することを提案しています。
_"requests" : {
"-KSVYZwUQPfyosiyRVdr" : {
"interests" : { "x": true },
"live" : true,
"uIds" : {
"user1": true,
"user2": true
}
},
"-KSl1L60g0tW5voyv0VU" : {
"interests" : { "y": true },
"live" : true,
"uIds" : {
"user2": true
}
}
}
_
このデータ構造がうまく機能する理由のいくつかを以下に示します。
ref.child("uUids").child("user3").setValue(true)
と同じくらい簡単になりました私は自分自身に繰り返し始めました:array.contains("xyz")
を実行していることに気づいたときは、おそらく配列の代わりにセットを使用する必要があります。_"key": true
_を使用した上記のマッピングは、Firebaseでのセットの実装です。
一部の人々は、配列がデータを保存するより効率的な方法であると考えるかもしれませんが、Firebaseの場合はそうではありません:
何が見える:
_"uIds" : [ "user1", "user2" ]
_
Firebaseが保存するもの:
_"uIds" : {
"0": "user1",
"1": "user2"
}
_
したがって、セットの保存はほとんど同じです。
_"uIds" : {
"user1": true,
"user2": true
}
_
SetValueなどと言うときの意味がわからないため、既存のデータを取得する必要があります。新しいレコードを挿入するための基本的なフローは次のとおりです。
_private DatabaseReference mDatabase;
// get reference to your Firebase Database.
mDatabase = FirebaseDatabase.getInstance().getReference();
//and here you add a new child to your 'requests' collection
//I am assuming you have a Request model like this..
Request newRequest = new Request(some-params);
mDatabase.child("requests").child(someRequestId).setValue(newRequest);
_
Saving Data on Android Firebase の基本的な使用ガイドをご覧ください。
更新:あなたのコメントに続いて-あなたがやろうとしていることは次のようにして達成できると思います:Push()
メソッドを使用します指定されたFirebase参照に新しい子が追加されるたびに一意のIDを生成します。
_Firebase newRequestRef = mDatabase.child("request").Push();
newRequestRef.setValue(newRequest);
_
これでうまくいくはずです。
これがお役に立てば幸いです。
Firebase公式ブログには、データベース内で配列を避けるべき理由を説明する古き良き記事があります。 Arrays are Evil
そのため、配列を置き換えずに配列を変更することはできません。データベース構造をこれに変更することをお勧めします
"requests" : {
"<pushKey1>" : {
"interests" : [ "x" ],
"live" : true,
"uIds" : {
"<pushKey1>" : "user1",
"<pushKey2>" : "user2"
}
},
"<pushKey2>" : {
"interests" : [ "y" ],
"live" : true,
"uIds" : {
"<pushKey1>" : "user2"
}
}
}
pushKey
を取得するには、 Push() メソッドを使用できます(各Request
アイテムに行った操作と同じ)
リクエストに新しいuidを追加するだけの場合、コードは次のようになります。
String requestKey = "request001";
mDatabase.child("requests").child(requestKey).child("uIds").Push().setValue("user2");
質問がある場合はここにコメントしてください、これが役立つことを願っています:)
Frank van Puffelenの回答に2セントを追加すると、Push操作のキーをリクエストの一意の識別子として使用できます。さらに、ハッシュマップを使用して子を更新する場合、DBはオーバーライドされません
// Create a node on Server and get key
String requestID = AdminController.getInstance().referenceFromUrl
.child(END_POINT_REQUESTS)
.Push().getKey();
//use key as ID for your Object which you want to Push as unique identifier of your model
requestToPush.setRequestId(requestID );
//Add updated Model Object in a Map to update DB instead of over writing
requestsMap.put(requestID , requestToPush);
//Update newly created DB nodes with data
referenceFromUrl
.child(END_POINT_REQUESTS)
.updateChildren(productsMap,
new DatabaseReference.CompletionListener() {
@Override
public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
if (databaseError != null) {
Log.e(TAG, "Error: Data could not be saved "
+ databaseError.getMessage());
} else {
Log.e(TAG, "Success : Data saved successfully.");
}
}
});
結果