我有以下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)
将用“newRequest”覆盖“request001”。所以我应该检索“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
。
答案 0 :(得分:16)
Firebase documentation on creating data that scales建议您使用不同的数据结构:
"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")
时,你应该使用一个集而不是一个数组。上面的映射与{{1} }是Firebase上的一个集合的实现。
有些人可能会认为数组是一种更有效的数据存储方式,但对于Firebase而言并非如此:
你看到了什么:
"key": true
Firebase存储的内容:
"uIds" : [ "user1", "user2" ]
所以存储一组几乎是一样的:
"uIds" : {
"0": "user1",
"1": "user2"
}
答案 1 :(得分:3)
当您说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的基本使用指南。
<强>更新强>
在您的评论之后 - 我认为您要做的事情可以像这样实现:
每次将新子项添加到指定的Firebase引用时,您都会使用push()
方法生成唯一ID:
Firebase newRequestRef = mDatabase.child("request").push();
newRequestRef.setValue(newRequest);
这应该这样做。
我希望这会有所帮助。
答案 2 :(得分:2)
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");
如果您有疑问,请在此处发表评论,希望这有助于:)
答案 3 :(得分:1)
向Frank van Puffelen回答加2美分,您可以使用推送操作中的密钥作为您请求的唯一标识符。此外,如果您使用哈希映射来更新子级,那么您的数据库将不会被覆盖
// 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.");
}
}
});
<强>结果强>