Android Firebase数据库-如果每个值都有一个随机生成的键,那么在推送到数据库之前如何确保值的唯一性

Android Firebase数据库-如果每个值都有一个随机生成的键,那么在推送到数据库之前如何确保值的唯一性,android,firebase,firebase-realtime-database,Android,Firebase,Firebase Realtime Database,我正在使用Android SDK将设备令牌写入Firebase数据库。我正在将这些令牌与用户关联。我假设每个用户可能有一个或多个设备。因此,我当前的数据库结构是这样的: { "users" : { "1" : { "-LAwu8VKATAxifCOZIPn" : "Device_Token_For_User_1", "-LAwyfXcoLcXBX3rOshb" : "Device_Token_For_User_1" }, "8" : {

我正在使用Android SDK将设备令牌写入Firebase数据库。我正在将这些令牌与用户关联。我假设每个用户可能有一个或多个设备。因此,我当前的数据库结构是这样的:

{
  "users" : {
    "1" : {
      "-LAwu8VKATAxifCOZIPn" : "Device_Token_For_User_1",
      "-LAwyfXcoLcXBX3rOshb" : "Device_Token_For_User_1"
    },
    "8" : {
      "-LAwuR9cel-p0kXv-LCn" : "Device_Token_For_User_8"
    }
  }
}
如您所见,由键1表示的用户1包含两次写入的相同令牌,但左侧的键不同。这些关键点是随机生成的,因为推送方法。实际上,我只关心值本身,但我希望避免将同一令牌多次写入特定用户

我通过以下方式将令牌推入我的数据库到Firebase数据库中:

String token = FirebaseInstanceId.getInstance().getToken();
Person currentUser;
try {
    currentUser = Reservoir.get("current_user", Person.class);
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference myRef = database.getReference();
    myRef.child("users").child(Integer.toString(currentUser.id)).push().setValue(token);
} catch (IOException e) {
    Log.e("ERROR", "Cannot fetch user from reservoir.");
    Toast.makeText(getApplicationContext(), "An unexpected error occurred.", Toast.LENGTH_SHORT).show();
    e.printStackTrace();
}

一切正常,只是当用户注销并重新登录到同一设备时,同一令牌将被推送到数据库两次,这是用户1的情况。

最好使用userido,然后您可以检查该令牌是否存在于数据库中,如果不存在,则可以将其添加到数据库中

String token = FirebaseInstanceId.getInstance().getToken();
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference();
FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();

myRef.orderByChild(user.getUid()).equalTo(token).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if(!dataSnapshot.exists()){
               myRef.child("users").child(user.getUid()).setValue(token);
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });

您可以使用令牌作为密钥,而不是使用令牌作为值,以确保它是唯一的,并为其指定任意值,如true

您必须按如下方式更改代码:

myRef.child("users").child(Integer.toString(currentUser.id)).child(token).setValue(true);
这将生成以下数据库:

{
  "users" : {
    "1" : {
      "Device_Token_For_User_1" : true,
      "SecondDevice_Token_For_User_1" : true
    },
    "8" : {
      "Device_Token_For_User_8" : true
    }
  }
}

为什么不使用令牌作为密钥并给它一个任意值,如true?另一个人建议我使用REST API直接从客户端向服务器发送令牌,并将令牌添加为用户的属性,我确实考虑过这一点,但这涉及到在person表中添加另一列,重构大约50个或更多的SQL函数。我认为,就目前而言,最好在我的用例中使用Firebase db。